muhammadhamza-stack commited on
Commit
1ff1745
·
1 Parent(s): 78f8def

dockerize the app

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ *.jpg filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ venv
2
+ outputs
3
+ .cache
4
+ debug
Dockerfile ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.9-slim
2
+
3
+ ENV PYTHONDONTWRITEBYTECODE=1
4
+ ENV PYTHONUNBUFFERED=1
5
+
6
+ WORKDIR /app
7
+
8
+ # Required for OpenCV image display & ultralytics
9
+ RUN apt-get update && apt-get install -y \
10
+ libgl1 \
11
+ libglib2.0-0 \
12
+ git \
13
+ curl \
14
+ && rm -rf /var/lib/apt/lists/*
15
+
16
+ COPY requirements.txt .
17
+
18
+ RUN pip install --upgrade pip \
19
+ && pip install --no-cache-dir -r requirements.txt
20
+
21
+ COPY . .
22
+
23
+ EXPOSE 7860
24
+
25
+ CMD ["python", "app.py"]
README.md CHANGED
@@ -3,7 +3,7 @@ title: Contour Detection Paper
3
  emoji: 👀
4
  colorFrom: pink
5
  colorTo: blue
6
- sdk: gradio
7
  # sdk_version: 5.41.1
8
  sdk_version: 5.42.0
9
  python_version: 3.12.0
 
3
  emoji: 👀
4
  colorFrom: pink
5
  colorTo: blue
6
+ sdk: docker
7
  # sdk_version: 5.41.1
8
  sdk_version: 5.42.0
9
  python_version: 3.12.0
app.py CHANGED
@@ -1032,43 +1032,83 @@ def predict_full_paper(image, paper_size, offset_value_mm = 0.02,offset_unit='mm
1032
  scale_info # Always return scaling info
1033
  )
1034
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1035
  # Gradio Interface
1036
  if __name__ == "__main__":
1037
  os.makedirs("./outputs", exist_ok=True)
 
 
 
 
 
 
 
 
 
1038
 
1039
  with gr.Blocks(title="Paper-Based DXF Generator", theme=gr.themes.Soft()) as demo:
1040
- # Example gallery
1041
- gr.Markdown("""
1042
- # Paper-Based DXF Generator
1043
-
1044
- Upload an image with a single object placed on paper (A4, A3, or US Letter).
1045
- The paper serves as a size reference for accurate DXF generation.
1046
- """)
1047
- with gr.Row():
1048
- gr.Markdown("""
1049
- **Instructions:**
1050
- 1. Place a single object on paper
1051
- 2. Select the correct paper size
1052
- 3. Configure options as needed
1053
- 4. Click Submit to generate DXF
1054
- """)
1055
- gr.Markdown("""
1056
- ### Tips for Best Results:
1057
- - Ensure good lighting and clear paper edges
1058
- - Place object completely at the center of the paper
1059
- - Avoid shadows that might interfere with detection
1060
- - Use high contrast between object and paper
1061
- """)
1062
 
1063
 
1064
  with gr.Row():
1065
  with gr.Column():
 
1066
  input_image = gr.Image(
1067
  label="Input Image (Object on Paper)",
1068
  type="numpy",
1069
  height=400
1070
  )
1071
-
 
1072
  paper_size = gr.Radio(
1073
  choices=["A4", "A3", "US Letter"],
1074
  value="A4",
@@ -1076,42 +1116,23 @@ if __name__ == "__main__":
1076
  info="Select the paper size used in your image"
1077
  )
1078
 
1079
- # with gr.Group():
1080
- # gr.Markdown("### Contour Offset")
1081
- # with gr.Row():
1082
- # offset_value_mm = gr.Number(
1083
- # value=0.02,
1084
- # label="Offset",
1085
- # info="Expand contours outward by this amount",
1086
- # precision=3,
1087
- # minimum=0,
1088
- # maximum=50
1089
- # )
1090
- # offset_unit = gr.Dropdown(
1091
- # choices=["mm", "inches"],
1092
- # value="mm",
1093
- # label="Unit"
1094
- # )
1095
-
1096
- # with gr.Group():
1097
- # gr.Markdown("### Finger Cuts")
1098
- # enable_finger_cut = gr.Radio(
1099
- # choices=["On", "Off"],
1100
- # value="Off",
1101
- # label="Enable Finger Cuts",
1102
- # info="Add circular cuts for easier handling"
1103
- # )
1104
 
1105
  output_options = gr.CheckboxGroup(
1106
  choices=["Annotated Image", "Outlines", "Mask"],
1107
- value=[],
1108
  label="Additional Outputs",
1109
  info="DXF is always included"
1110
  )
1111
 
 
 
 
1112
  submit_btn = gr.Button("Generate DXF", variant="primary", size="lg")
1113
 
 
1114
  with gr.Column():
 
1115
  with gr.Group():
1116
  gr.Markdown("### Generated Files")
1117
  dxf_file = gr.File(label="DXF File", file_types=[".dxf"])
@@ -1119,8 +1140,8 @@ if __name__ == "__main__":
1119
 
1120
  with gr.Group():
1121
  gr.Markdown("### Preview Images")
1122
- output_image = gr.Image(label="Annotated Image", visible=False)
1123
- outlines_image = gr.Image(label="Outlines", visible=False)
1124
  mask_image = gr.Image(label="Mask", visible=False)
1125
 
1126
  def update_outputs_visibility(selected):
@@ -1150,6 +1171,25 @@ if __name__ == "__main__":
1150
  outputs=[dxf_file, output_image, outlines_image, mask_image, scale_info]
1151
  )
1152
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1153
 
1154
 
1155
- demo.launch(share=True)
 
 
 
 
 
1032
  scale_info # Always return scaling info
1033
  )
1034
 
1035
+ # ---------------------
1036
+ # Documentation Strings for Gradio
1037
+ # ---------------------
1038
+
1039
+ QUICK_START_PAPER = """
1040
+ ## 1. Quick Start Guide: From Photo to DXF Cut File
1041
+ This application converts a photograph of a single object placed on a sheet of standard paper (A4, A3, or US Letter) into a precise DXF contour file for CNC cutting. The paper acts as the scale reference.
1042
+
1043
+ 1. **Preparation**: Place **only one object** (tool, part, etc.) flat on a sheet of A4, A3, or US Letter paper. Ensure the paper is fully visible and the object is fully within the boundaries of the paper. Use clear, overhead lighting.
1044
+ 2. **Upload**: Upload the image in the **Input Image** box.
1045
+ 3. **Configure**: Select the correct `Paper Size`. The default clearance is **0.02 mm** with **Finger Cuts Off**.
1046
+ 4. **Run**: Click the **"Generate DXF"** button.
1047
+ 5. **Download**: Review the previews, then download the final **DXF file** containing the object's profile, accurately scaled.
1048
+ """
1049
+
1050
+ INPUT_EXPLANATION_PAPER = """
1051
+ ## 2. Expected Inputs
1052
+ ### Image Requirements
1053
+ * **Paper is Mandatory:** The system uses the known dimensions of the standard paper size (A4, A3, or US Letter) to calculate the real-world scale (mm/pixel).
1054
+ * **Single Object Only:** The system is designed to detect and contour only **one** significant object on the paper. Multiple objects or major fragments will cause an error.
1055
+ * **Placement & Lighting:** The image should be taken from directly above (minimal perspective distortion). Clear, shadow-free lighting is essential.
1056
+ ### Processing Parameters (Hardcoded Default Values)
1057
+ | Parameter | Purpose | Default Value | Guidance for Non-Tech Clients |
1058
+ | :--- | :--- | :--- | :--- |
1059
+ | **Paper Size** | The exact size of the paper sheet used in the image. | A4 | Must match the paper you used for accurate scaling. |
1060
+ | **Offset Value** | The amount of space (clearance) added around the object profile. | **0.02 mm** | This minimal buffer ensures the cut is slightly larger than the object. (Cannot be changed in the UI) |
1061
+ | **Finger Cuts** | Adds a small circular cutout for easy object removal. | **Off** | Cannot be changed in the UI. |
1062
+ """
1063
+
1064
+ OUTPUT_EXPLANATION_PAPER = """
1065
+ ## 3. Expected Outputs
1066
+ | Output Field | Description | Purpose |
1067
+ | :--- | :--- | :--- |
1068
+ | **DXF file** | The final vector file containing the object's profile. All coordinates are in millimeters (MM). | Ready to upload to CNC machine software (AutoCAD DXF R2000 format). |
1069
+ | **Scaling Information**| The calculated real-world scale (mm per pixel) determined by the paper reference, plus the offset settings. | Confirmation of measurement accuracy. |
1070
+ | **Annotated Image** | The original image overlaid with the final generated outline (including offset and finger cuts). | Visual confirmation that the detection and sizing are correct relative to the original photo. |
1071
+ | **Outlines**| A clean, scaled, white-background image showing only the outlines (black lines). This visually represents the final geometry exported to the DXF. | Final quality check for shape before CNC cutting. |
1072
+ | **Mask (Technical)** | The binary image used internally to generate the contours after applying segmentation. | Technical output for debugging segmentation issues. |
1073
+ """
1074
+
1075
  # Gradio Interface
1076
  if __name__ == "__main__":
1077
  os.makedirs("./outputs", exist_ok=True)
1078
+ os.makedirs("./debug", exist_ok=True)
1079
+
1080
+ # Define HIDDEN inputs for the function signature, as requested.
1081
+ # These mimic the original inline hardcoded values.
1082
+ # NOTE: We must use named variables so gr.Examples can reference them.
1083
+ hidden_offset_value = gr.Number(value=0.02, visible=False, label="Hidden Offset Value")
1084
+ hidden_offset_unit = gr.Textbox(value='mm', visible=False, label="Hidden Offset Unit")
1085
+ hidden_enable_finger_cut = gr.Textbox(value='Off', visible=False, label="Hidden Finger Cut")
1086
+
1087
 
1088
  with gr.Blocks(title="Paper-Based DXF Generator", theme=gr.themes.Soft()) as demo:
1089
+
1090
+ gr.Markdown("<h1 style='text-align: center;'> Paper-Based DXF Generator </h1>")
1091
+ gr.Markdown("Upload an image with a single object placed on standard paper (A4, A3, or US Letter). The paper serves as the scale reference.")
1092
+
1093
+ # 1. Guidelines & Instructions (Integrated Documentation)
1094
+ with gr.Accordion("Tips & User Guide", open=False):
1095
+ gr.Markdown(QUICK_START_PAPER)
1096
+ gr.Markdown("---")
1097
+ gr.Markdown(INPUT_EXPLANATION_PAPER)
1098
+ gr.Markdown("---")
1099
+ gr.Markdown(OUTPUT_EXPLANATION_PAPER)
 
 
 
 
 
 
 
 
 
 
 
1100
 
1101
 
1102
  with gr.Row():
1103
  with gr.Column():
1104
+ gr.Markdown("## Step 1: Upload Image ")
1105
  input_image = gr.Image(
1106
  label="Input Image (Object on Paper)",
1107
  type="numpy",
1108
  height=400
1109
  )
1110
+ with gr.Column():
1111
+ gr.Markdown("## Step 2: Select Paper Size & Preview Outputs")
1112
  paper_size = gr.Radio(
1113
  choices=["A4", "A3", "US Letter"],
1114
  value="A4",
 
1116
  info="Select the paper size used in your image"
1117
  )
1118
 
1119
+ # Hidden components are defined but not visible in the UI layout
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1120
 
1121
  output_options = gr.CheckboxGroup(
1122
  choices=["Annotated Image", "Outlines", "Mask"],
1123
+ value=["Annotated Image", "Outlines"],
1124
  label="Additional Outputs",
1125
  info="DXF is always included"
1126
  )
1127
 
1128
+ with gr.Row():
1129
+ with gr.Column():
1130
+ gr.Markdown("## Step 3: Click Generate DXF ")
1131
  submit_btn = gr.Button("Generate DXF", variant="primary", size="lg")
1132
 
1133
+ with gr.Row():
1134
  with gr.Column():
1135
+ gr.Markdown("## Outputs ")
1136
  with gr.Group():
1137
  gr.Markdown("### Generated Files")
1138
  dxf_file = gr.File(label="DXF File", file_types=[".dxf"])
 
1140
 
1141
  with gr.Group():
1142
  gr.Markdown("### Preview Images")
1143
+ output_image = gr.Image(label="Annotated Image", visible=True)
1144
+ outlines_image = gr.Image(label="Outlines", visible=True)
1145
  mask_image = gr.Image(label="Mask", visible=False)
1146
 
1147
  def update_outputs_visibility(selected):
 
1171
  outputs=[dxf_file, output_image, outlines_image, mask_image, scale_info]
1172
  )
1173
 
1174
+ # 4. Examples Section
1175
+ gr.Markdown("---")
1176
+ gr.Markdown("## Examples")
1177
+ gr.Examples(
1178
+ examples=[
1179
+ # [Input Image Path, Paper Size, Selected Outputs]
1180
+ # NOTE: The image paths below are placeholders. Ensure these files exist in ./examples/
1181
+ ["./sample_data/papertest1.jpg", "A4", ["Annotated Image", "Outlines"]],
1182
+ ["./sample_data/papertest2.jpg", "US Letter", ["Annotated Image", "Outlines", "Mask"]],
1183
+ ["./sample_data/papertest3.jpg", "A3", ["Annotated Image", "Outlines"]],
1184
+ ],
1185
+ inputs=[input_image, paper_size, output_options],
1186
+ label="Click an example to load the image and configuration. Then click 'Generate DXF'."
1187
+ )
1188
+
1189
 
1190
 
1191
+ demo.launch(
1192
+ server_name = "0.0.0.0",
1193
+ server_port=7860
1194
+ )
1195
+
requirements.txt CHANGED
@@ -5,12 +5,16 @@ pydantic==2.10.6
5
  opencv-python-headless>=4.8.0
6
  opencv-contrib-python-headless>=4.8.0
7
  ezdxf==1.3.5
8
- gradio==5.15.0
9
  kornia==0.8.0
10
  timm==1.0.14
11
  einops==0.8.1
12
- torchvision==0.20.1
13
- torch==2.5.1
14
- torchaudio==2.5.1
 
15
  shapely
16
- git+https://github.com/ultralytics/CLIP.git
 
 
 
 
 
5
  opencv-python-headless>=4.8.0
6
  opencv-contrib-python-headless>=4.8.0
7
  ezdxf==1.3.5
 
8
  kornia==0.8.0
9
  timm==1.0.14
10
  einops==0.8.1
11
+ torch==2.2.2
12
+ torchaudio==2.2.2
13
+ torchmetrics==1.8.2
14
+ torchvision==0.17.2
15
  shapely
16
+ git+https://github.com/ultralytics/CLIP.git
17
+ Pillow
18
+ numpy<2
19
+ gradio==3.50.2
20
+ gradio-client==0.6.1
sample_data/papertest1.jpg ADDED

Git LFS Details

  • SHA256: bd3c995e8bb219c808de9b3ff99c5991267cb72a408924e4e35cb86e0f781c90
  • Pointer size: 131 Bytes
  • Size of remote file: 456 kB
sample_data/papertest2.jpg ADDED

Git LFS Details

  • SHA256: dc0f3740a21df5d2ae22a0d11c7de98201308ea95ed64615cd4d3b59c89bfbde
  • Pointer size: 131 Bytes
  • Size of remote file: 694 kB
sample_data/papertest3.JPG ADDED

Git LFS Details

  • SHA256: 64dbd8c095d389514df717cc9a03211b63c3cb2b2ab324401bb8a46e753308cb
  • Pointer size: 132 Bytes
  • Size of remote file: 8.09 MB