├── Test ├── tempCodeRunnerFile.py ├── output.svg ├── output.jpg ├── bezier_image.png ├── occlusion1_rec.png ├── occlusion2_rec.png ├── occlusion1_sol_rec.png ├── occlusion2_sol_rec.png ├── isolated_sol.svg ├── frag01_sol.svg ├── occlusion2_sol.svg ├── frag2_sol.svg ├── input.svg ├── frag0.svg ├── occlusion1_sol.svg ├── occlusion2.svg ├── isolated.svg ├── occlusion1.svg ├── frag2_sol.csv ├── frag2.svg ├── solution_adb.py ├── bezier_control_points.json ├── occlusion1_sol_rec.svg └── occlusion1_rec.svg ├── Adobe V2 ├── ct.png ├── op.png ├── ball.png ├── cir.png ├── occ.png ├── rect.png ├── rtri.png ├── star.jpg ├── star.png ├── tri.png ├── bfly.jpeg ├── feather.jpg ├── image.png ├── lines.png ├── test1.png ├── butterfly.png ├── scissor.jpeg ├── symmetry_analysis.png ├── input.svg ├── shape.py ├── frag0.svg ├── occlusion2.svg ├── webapp │ ├── static │ │ └── particles.json │ ├── app.py │ └── templates │ │ └── index.html ├── test.py ├── symmetry.py ├── symm2.py ├── tempCodeRunnerFile.py ├── frag2.svg └── test_indra.py ├── detected_shapes.jpg ├── regularized_output.jpg ├── tempCodeRunnerFile.py ├── model ├── tempCodeRunnerFile.py ├── gptmod.py ├── finalv3.py ├── test.py ├── model.py ├── test.ipynb └── finalv1.ipynb ├── regularize.py ├── test2.py ├── Backup Adobe └── 1.txt ├── main.py └── Adobe Shape Complettion └── comp.py /Test/tempCodeRunnerFile.py: -------------------------------------------------------------------------------- 1 | input -------------------------------------------------------------------------------- /Test/output.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Adobe V2/ct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Adobe V2/ct.png -------------------------------------------------------------------------------- /Adobe V2/op.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Adobe V2/op.png -------------------------------------------------------------------------------- /Test/output.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Test/output.jpg -------------------------------------------------------------------------------- /Adobe V2/ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Adobe V2/ball.png -------------------------------------------------------------------------------- /Adobe V2/cir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Adobe V2/cir.png -------------------------------------------------------------------------------- /Adobe V2/occ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Adobe V2/occ.png -------------------------------------------------------------------------------- /Adobe V2/rect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Adobe V2/rect.png -------------------------------------------------------------------------------- /Adobe V2/rtri.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Adobe V2/rtri.png -------------------------------------------------------------------------------- /Adobe V2/star.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Adobe V2/star.jpg -------------------------------------------------------------------------------- /Adobe V2/star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Adobe V2/star.png -------------------------------------------------------------------------------- /Adobe V2/tri.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Adobe V2/tri.png -------------------------------------------------------------------------------- /Adobe V2/bfly.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Adobe V2/bfly.jpeg -------------------------------------------------------------------------------- /Adobe V2/feather.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Adobe V2/feather.jpg -------------------------------------------------------------------------------- /Adobe V2/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Adobe V2/image.png -------------------------------------------------------------------------------- /Adobe V2/lines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Adobe V2/lines.png -------------------------------------------------------------------------------- /Adobe V2/test1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Adobe V2/test1.png -------------------------------------------------------------------------------- /detected_shapes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/detected_shapes.jpg -------------------------------------------------------------------------------- /Adobe V2/butterfly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Adobe V2/butterfly.png -------------------------------------------------------------------------------- /Adobe V2/scissor.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Adobe V2/scissor.jpeg -------------------------------------------------------------------------------- /Test/bezier_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Test/bezier_image.png -------------------------------------------------------------------------------- /regularized_output.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/regularized_output.jpg -------------------------------------------------------------------------------- /Test/occlusion1_rec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Test/occlusion1_rec.png -------------------------------------------------------------------------------- /Test/occlusion2_rec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Test/occlusion2_rec.png -------------------------------------------------------------------------------- /Test/occlusion1_sol_rec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Test/occlusion1_sol_rec.png -------------------------------------------------------------------------------- /Test/occlusion2_sol_rec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Test/occlusion2_sol_rec.png -------------------------------------------------------------------------------- /Adobe V2/symmetry_analysis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvcops/Adobe/main/Adobe V2/symmetry_analysis.png -------------------------------------------------------------------------------- /tempCodeRunnerFile.py: -------------------------------------------------------------------------------- 1 | "C:\\Users\\vamsi\\OneDrive\\Pictures\\Screenshots\\Screenshot 2024-07-31 124836.png -------------------------------------------------------------------------------- /model/tempCodeRunnerFile.py: -------------------------------------------------------------------------------- 1 | for chunk in df_iterator: 2 | # Convert JSON drawings to images 3 | chunk['image'] = chunk['drawing'].apply(json_to_image) 4 | 5 | # Apply regularization to all images 6 | chunk['regularized'] = chunk['image'].apply(regularize_shape) 7 | 8 | # Append to lists 9 | X_list.extend(chunk['image'].tolist()) 10 | y_list.extend(chunk['regularized'].tolist()) 11 | 12 | print(f"Processed {len(X_list)} images so far...") 13 | 14 | # Optional: break after processing a certain number of images 15 | if len(X_list) >= 10000: # Adjust this number as needed 16 | break -------------------------------------------------------------------------------- /Test/isolated_sol.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Test/frag01_sol.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Test/occlusion2_sol.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Test/frag2_sol.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Test/input.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Adobe V2/input.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Adobe V2/shape.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | from tensorflow import keras 3 | import numpy as np 4 | from PIL import Image 5 | 6 | # Load the pre-trained MobileNetV2 model 7 | model = keras.applications.MobileNetV2(weights='imagenet', include_top=False, input_shape=(224, 224, 3)) 8 | 9 | # Freeze the layers of the pre-trained model 10 | for layer in model.layers: 11 | layer.trainable = False 12 | 13 | # Add a new classification head on top of the pre-trained model 14 | x = model.output 15 | x = keras.layers.GlobalAveragePooling2D()(x) 16 | x = keras.layers.Dense(128, activation='relu')(x) 17 | x = keras.layers.Dropout(0.2)(x) 18 | x = keras.layers.Dense(10, activation='softmax')(x) 19 | 20 | # Create a new model with the classification head 21 | model = keras.Model(inputs=model.input, outputs=x) 22 | 23 | # Compile the model 24 | model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) 25 | 26 | # Define a function to detect the shape of a doodle 27 | def detect_doodle(image_path): 28 | # Load the image 29 | image = Image.open(image_path) 30 | image = image.resize((224, 224)) 31 | image = np.array(image) / 255.0 32 | image = np.expand_dims(image, axis=0) 33 | 34 | # Make predictions 35 | predictions = model.predict(image) 36 | predicted_class = np.argmax(predictions) 37 | 38 | # Map the predicted class to a shape label 39 | shape_labels = ['circle', 'square', 'triangle', 'rectangle', 'pentagon', 'hexagon', 'star', 'heart', 'oval', 'unknown'] 40 | predicted_shape = shape_labels[predicted_class] 41 | 42 | return predicted_shape 43 | 44 | # Test the function 45 | image_path = 'star.png' 46 | predicted_shape = detect_doodle(image_path) 47 | print(predicted_shape) -------------------------------------------------------------------------------- /Test/frag0.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Adobe V2/frag0.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Test/occlusion1_sol.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /regularize.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | 5 | # Load the image 6 | image_path = 'C:\\Users\\vamsi\\OneDrive\\Desktop\\ball.png' 7 | image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) 8 | 9 | # Apply GaussianBlur to smoothen the image 10 | blurred_image = cv2.GaussianBlur(image, (5, 5), 0) 11 | 12 | # Use Canny edge detection to detect edges 13 | edges = cv2.Canny(blurred_image, 50, 150) 14 | 15 | # Detect contours 16 | contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 17 | 18 | # Create an empty image to draw the regularized shapes 19 | regularized_image = np.zeros_like(image) 20 | 21 | # Function to draw regularized shapes 22 | def draw_regularized_shapes(contours, output_image): 23 | for contour in contours: 24 | # Approximate the contour using Ramer-Douglas-Peucker algorithm 25 | epsilon = 0.01 * cv2.arcLength(contour, True) 26 | approx_contour = cv2.approxPolyDP(contour, epsilon, True) 27 | 28 | # Fit an ellipse if the contour has more than 5 points 29 | if len(approx_contour) >= 5: 30 | ellipse = cv2.fitEllipse(approx_contour) 31 | cv2.ellipse(output_image, ellipse, (255), 2) 32 | else: 33 | # Draw the approximated contour 34 | cv2.drawContours(output_image, [approx_contour], -1, (255), 2) 35 | 36 | return output_image 37 | 38 | # Draw regularized shapes 39 | regularized_image = draw_regularized_shapes(contours, regularized_image) 40 | 41 | # Display the result 42 | plt.figure(figsize=(10, 10)) 43 | plt.subplot(1, 2, 1) 44 | plt.title('Original Image') 45 | plt.imshow(image, cmap='gray') 46 | 47 | plt.subplot(1, 2, 2) 48 | plt.title('Regularized Image') 49 | plt.imshow(regularized_image, cmap='gray') 50 | 51 | plt.show() -------------------------------------------------------------------------------- /test2.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | def fill_gaps(image_path): 5 | # Read the image 6 | image = cv2.imread(image_path) 7 | 8 | # Convert to grayscale 9 | gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 10 | 11 | # Threshold the image to get a binary image 12 | _, binary = cv2.threshold(gray, 128, 255, cv2.THRESH_BINARY_INV) 13 | 14 | # Find contours 15 | contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 16 | 17 | # Find the largest contour (assuming it's the apple outline) 18 | largest_contour = max(contours, key=cv2.contourArea) 19 | 20 | # Create a mask of the largest contour 21 | mask = np.zeros(gray.shape, np.uint8) 22 | cv2.drawContours(mask, [largest_contour], 0, 255, -1) 23 | 24 | # Create a color-filled version of the apple 25 | color_fill = np.zeros_like(image) 26 | 27 | # Determine the dominant color in the apple 28 | apple_region = cv2.bitwise_and(image, image, mask=mask) 29 | dominant_color = np.mean(apple_region, axis=(0, 1)).astype(int) 30 | 31 | # Fill the apple with the dominant color 32 | color_fill[mask == 255] = dominant_color 33 | 34 | # Blend the original image with the color-filled version 35 | result = cv2.addWeighted(image, 0.3, color_fill, 0.7, 0) 36 | 37 | # Draw the outline 38 | cv2.drawContours(result, [largest_contour], 0, (0, 255, 0), 2) 39 | 40 | return result 41 | 42 | # Main execution 43 | input_image_path = "C:\\Users\\vamsi\\OneDrive\\Pictures\\Screenshots\\Screenshot 2024-07-31 124836.png" 44 | output_image = fill_gaps(input_image_path) 45 | 46 | # Display the result 47 | cv2.imshow("Filled Apple", output_image) 48 | cv2.waitKey(0) 49 | cv2.destroyAllWindows() 50 | 51 | # Save the result 52 | cv2.imwrite("filled_apple.png", output_image) -------------------------------------------------------------------------------- /Test/occlusion2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Adobe V2/occlusion2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Test/isolated.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Test/occlusion1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Backup Adobe/1.txt: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | import svgwrite 4 | from svgpathtools import Path, Line, QuadraticBezier, CubicBezier, Arc 5 | from svgpathtools import wsvg 6 | import matplotlib.pyplot as plt 7 | 8 | def preprocess_image(image_path): 9 | # Load the image in grayscale 10 | img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) 11 | 12 | # Apply GaussianBlur to remove noise 13 | blur = cv2.GaussianBlur(img, (5, 5), 0) 14 | 15 | # Apply adaptive thresholding to get a binary image 16 | thresh = cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 17 | cv2.THRESH_BINARY_INV, 11, 2) 18 | 19 | return thresh 20 | 21 | def detect_shapes(binary_image): 22 | # Find contours 23 | contours, _ = cv2.findContours(binary_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 24 | return contours 25 | 26 | def vectorize_shapes(contours, output_svg_path): 27 | dwg = svgwrite.Drawing(output_svg_path, profile='tiny') 28 | 29 | for contour in contours: 30 | # Approximate the contour to a simpler shape 31 | epsilon = 0.01 * cv2.arcLength(contour, True) 32 | approx = cv2.approxPolyDP(contour, epsilon, True) 33 | 34 | path = "M " 35 | for point in approx: 36 | x, y = point[0] 37 | path += f"{x},{y} " 38 | 39 | path += "Z" 40 | dwg.add(dwg.path(d=path, fill='none', stroke=svgwrite.rgb(10, 10, 16, '%'))) 41 | 42 | dwg.save() 43 | 44 | def main(image_path, output_svg_path): 45 | # Preprocess the image 46 | binary_image = preprocess_image(image_path) 47 | 48 | # Detect shapes in the image 49 | contours = detect_shapes(binary_image) 50 | 51 | # Vectorize the detected shapes 52 | vectorize_shapes(contours, output_svg_path) 53 | 54 | print(f"Vectorized image saved to {output_svg_path}") 55 | 56 | # Example usage 57 | image_path = 'image.png' 58 | output_svg_path = 'output_image.svg' 59 | main(image_path, output_svg_path) 60 | -------------------------------------------------------------------------------- /Adobe V2/webapp/static/particles.json: -------------------------------------------------------------------------------- 1 | { 2 | "particles": { 3 | "number": { 4 | "value": 80, 5 | "density": { 6 | "enable": true, 7 | "value_area": 800 8 | } 9 | }, 10 | "color": { 11 | "value": "#ffffff" 12 | }, 13 | "shape": { 14 | "type": "circle", 15 | "stroke": { 16 | "width": 0, 17 | "color": "#000000" 18 | }, 19 | "polygon": { 20 | "nb_sides": 5 21 | } 22 | }, 23 | "opacity": { 24 | "value": 0.5, 25 | "random": true, 26 | "anim": { 27 | "enable": true, 28 | "speed": 1, 29 | "opacity_min": 0.1, 30 | "sync": false 31 | } 32 | }, 33 | "size": { 34 | "value": 3, 35 | "random": true, 36 | "anim": { 37 | "enable": true, 38 | "speed": 2, 39 | "size_min": 0.1, 40 | "sync": false 41 | } 42 | }, 43 | "line_linked": { 44 | "enable": true, 45 | "distance": 150, 46 | "color": "#ffffff", 47 | "opacity": 0.4, 48 | "width": 1 49 | }, 50 | "move": { 51 | "enable": true, 52 | "speed": 1, 53 | "direction": "none", 54 | "random": true, 55 | "straight": false, 56 | "out_mode": "out", 57 | "bounce": false, 58 | "attract": { 59 | "enable": false, 60 | "rotateX": 600, 61 | "rotateY": 1200 62 | } 63 | } 64 | }, 65 | "interactivity": { 66 | "detect_on": "canvas", 67 | "events": { 68 | "onhover": { 69 | "enable": true, 70 | "mode": "grab" 71 | }, 72 | "onclick": { 73 | "enable": true, 74 | "mode": "push" 75 | }, 76 | "resize": true 77 | }, 78 | "modes": { 79 | "grab": { 80 | "distance": 140, 81 | "line_linked": { 82 | "opacity": 1 83 | } 84 | }, 85 | "bubble": { 86 | "distance": 400, 87 | "size": 40, 88 | "duration": 2, 89 | "opacity": 8, 90 | "speed": 3 91 | }, 92 | "repulse": { 93 | "distance": 200, 94 | "duration": 0.4 95 | }, 96 | "push": { 97 | "particles_nb": 4 98 | }, 99 | "remove": { 100 | "particles_nb": 2 101 | } 102 | } 103 | }, 104 | "retina_detect": true 105 | } -------------------------------------------------------------------------------- /Test/frag2_sol.csv: -------------------------------------------------------------------------------- 1 | 0.000000000000000000e+00,0.000000000000000000e+00,4.106000000000000227e+01,1.133500000000000085e+01 2 | 0.000000000000000000e+00,0.000000000000000000e+00,9.552400000000000091e+01,1.137780000000000058e+02 3 | 0.000000000000000000e+00,0.000000000000000000e+00,1.142980000000000018e+02,1.488389999999999986e+02 4 | 1.000000000000000000e+00,0.000000000000000000e+00,1.159699999999999953e+01,2.226099999999999923e+01 5 | 1.000000000000000000e+00,0.000000000000000000e+00,3.059400000000000119e+01,5.522999999999999687e+01 6 | 1.000000000000000000e+00,0.000000000000000000e+00,3.065700000000000003e+01,5.522399999999999665e+01 7 | 1.000000000000000000e+00,0.000000000000000000e+00,6.079999999999999716e+01,1.076310000000000002e+02 8 | 2.000000000000000000e+00,0.000000000000000000e+00,2.000000000000000000e+00,6.238900000000000290e+01 9 | 2.000000000000000000e+00,0.000000000000000000e+00,3.059400000000000119e+01,5.522999999999999687e+01 10 | 2.000000000000000000e+00,0.000000000000000000e+00,3.065700000000000003e+01,5.522399999999999665e+01 11 | 2.000000000000000000e+00,0.000000000000000000e+00,1.256219999999999999e+02,3.126599999999999824e+01 12 | 2.000000000000000000e+00,0.000000000000000000e+00,1.255580000000000069e+02,3.123600000000000065e+01 13 | 2.000000000000000000e+00,0.000000000000000000e+00,1.388940000000000055e+02,2.802199999999999847e+01 14 | 3.000000000000000000e+00,0.000000000000000000e+00,7.339100000000000534e+01,2.362000000000000099e+00 15 | 3.000000000000000000e+00,0.000000000000000000e+00,1.374389999999999930e+02,1.260709999999999980e+02 16 | 4.000000000000000000e+00,0.000000000000000000e+00,1.499019999999999868e+02,7.373499999999999943e+01 17 | 4.000000000000000000e+00,0.000000000000000000e+00,1.498940000000000055e+02,7.373799999999999955e+01 18 | 5.000000000000000000e+00,0.000000000000000000e+00,1.504579999999999984e+02,4.735799999999999699e+01 19 | 5.000000000000000000e+00,0.000000000000000000e+00,1.985200000000000031e+01,8.300799999999999557e+01 20 | 6.000000000000000000e+00,0.000000000000000000e+00,6.758299999999999841e+01,1.197579999999999956e+02 21 | 6.000000000000000000e+00,0.000000000000000000e+00,1.502309999999999945e+02,1.016850000000000023e+02 22 | 7.000000000000000000e+00,0.000000000000000000e+00,1.309800000000000075e+01,1.098940000000000055e+02 23 | 7.000000000000000000e+00,0.000000000000000000e+00,1.663789999999999907e+02,6.942300000000000182e+01 24 | 8.000000000000000000e+00,0.000000000000000000e+00,1.222270000000000039e+02,2.000000000000000000e+00 25 | 8.000000000000000000e+00,0.000000000000000000e+00,6.123000000000000220e+00,3.897299999999999898e+01 26 | 9.000000000000000000e+00,0.000000000000000000e+00,3.059400000000000119e+01,5.522999999999999687e+01 27 | 9.000000000000000000e+00,0.000000000000000000e+00,3.065700000000000003e+01,5.522399999999999665e+01 28 | 1.000000000000000000e+01,0.000000000000000000e+00,1.167519999999999953e+02,1.571299999999999919e+01 29 | 1.000000000000000000e+01,0.000000000000000000e+00,1.575000000000000000e+02,8.704099999999999682e+01 30 | 1.100000000000000000e+01,0.000000000000000000e+00,1.255580000000000069e+02,3.123600000000000065e+01 31 | 1.100000000000000000e+01,0.000000000000000000e+00,1.256219999999999999e+02,3.126599999999999824e+01 32 | -------------------------------------------------------------------------------- /model/gptmod.py: -------------------------------------------------------------------------------- 1 | # Step 1: Setup and Download the Dataset 2 | !pip install kaggle 3 | !mkdir -p ~/.kaggle 4 | !echo '{"username":"YOUR_KAGGLE_USERNAME","key":"YOUR_KAGGLE_KEY"}' > ~/.kaggle/kaggle.json 5 | !chmod 600 ~/.kaggle/kaggle.json 6 | !kaggle datasets download -d ashishjangra27/doodle-dataset 7 | !unzip doodle-dataset.zip -d doodle_dataset 8 | 9 | # Step 2: Data Preprocessing 10 | import os 11 | import cv2 12 | import numpy as np 13 | import pandas as pd 14 | from tensorflow.keras.utils import to_categorical 15 | from sklearn.model_selection import train_test_split 16 | 17 | # Load metadata 18 | metadata = pd.read_csv('doodle_dataset/master_doodle_dataframe.csv') 19 | 20 | # Function to load images 21 | def load_images(image_paths, img_size=(255, 255)): 22 | images = [] 23 | for path in image_paths: 24 | img = cv2.imread(path, cv2.IMREAD_GRAYSCALE) 25 | if img is not None: 26 | img = cv2.resize(img, img_size) 27 | images.append(img) 28 | return np.array(images) 29 | 30 | # Sample a subset of data for faster training 31 | sample_metadata = metadata.sample(n=10000, random_state=42) 32 | 33 | # Load images 34 | image_paths = sample_metadata['image_path'].values 35 | X = load_images(image_paths) 36 | 37 | # Normalize images 38 | X = X / 255.0 39 | X = X[..., np.newaxis] # Add channel dimension 40 | 41 | # Prepare labels 42 | y = pd.factorize(sample_metadata['word'])[0] 43 | y = to_categorical(y, num_classes=340) 44 | 45 | # Split data 46 | X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) 47 | 48 | # Step 3: Model Training 49 | import tensorflow as tf 50 | from tensorflow.keras.models import Sequential 51 | from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout 52 | 53 | # Define the model 54 | model = Sequential([ 55 | Conv2D(32, (3, 3), activation='relu', input_shape=(255, 255, 1)), 56 | MaxPooling2D((2, 2)), 57 | Conv2D(64, (3, 3), activation='relu'), 58 | MaxPooling2D((2, 2)), 59 | Conv2D(128, (3, 3), activation='relu'), 60 | MaxPooling2D((2, 2)), 61 | Flatten(), 62 | Dense(128, activation='relu'), 63 | Dropout(0.5), 64 | Dense(340, activation='softmax') 65 | ]) 66 | 67 | # Compile the model 68 | model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) 69 | 70 | # Train the model 71 | history = model.fit(X_train, y_train, epochs=10, validation_data=(X_test, y_test), batch_size=32) 72 | 73 | # Step 4: Inference and Visualization 74 | import matplotlib.pyplot as plt 75 | 76 | def visualize_regularization(image, prediction): 77 | # Placeholder visualization function 78 | plt.imshow(image.squeeze(), cmap='gray') 79 | plt.title(f'Predicted: {prediction}') 80 | plt.show() 81 | 82 | # Load a test image 83 | test_image_path = sample_metadata.sample(n=1)['image_path'].values[0] 84 | test_image = cv2.imread(test_image_path, cv2.IMREAD_GRAYSCALE) 85 | test_image = cv2.resize(test_image, (255, 255)) 86 | test_image_normalized = test_image / 255.0 87 | test_image_normalized = test_image_normalized[np.newaxis, ..., np.newaxis] 88 | 89 | # Predict 90 | prediction = model.predict(test_image_normalized) 91 | predicted_class = np.argmax(prediction) 92 | 93 | # Visualize 94 | visualize_regularization(test_image, predicted_class) 95 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import cv2 3 | from scipy.interpolate import splprep, splev 4 | 5 | def detect_curves(image): 6 | # Convert image to grayscale 7 | gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 8 | 9 | # Apply edge detection 10 | edges = cv2.Canny(gray, 50, 150, apertureSize=3) 11 | 12 | # Find contours 13 | contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 14 | 15 | return contours 16 | 17 | def identify_gaps(contour, gap_threshold=10): 18 | gaps = [] 19 | for i in range(len(contour)): 20 | dist = np.linalg.norm(contour[i] - contour[(i+1) % len(contour)]) 21 | if dist > gap_threshold: 22 | gaps.append((i, (i+1) % len(contour))) 23 | return gaps 24 | 25 | def complete_curve(contour, gaps): 26 | completed_curve = contour.copy() 27 | 28 | for start, end in gaps: 29 | # Extract points before and after the gap 30 | before = contour[max(0, start-5):start+1] 31 | after = contour[end:min(end+6, len(contour))] 32 | 33 | # Combine points and ensure correct shape 34 | points = np.concatenate([before, after]) 35 | points = points.reshape(-1, 2) # Ensure points are in the correct shape 36 | 37 | # Check if we have enough points for interpolation 38 | if len(points) < 4: 39 | continue # Skip this gap if we don't have enough points 40 | 41 | # Fit spline to points before and after the gap 42 | try: 43 | tck, u = splprep(points.T, s=0, k=min(3, len(points) - 1)) 44 | 45 | # Generate new points to fill the gap 46 | new_points = splev(np.linspace(0, 1, 20), tck) 47 | new_points = np.column_stack(new_points).astype(np.int32) 48 | 49 | # Insert new points into the curve 50 | completed_curve = np.insert(completed_curve, end, new_points, axis=0) 51 | except Exception as e: 52 | print(f"Error in curve completion: {e}") 53 | continue # Skip this gap if there's an error 54 | 55 | return completed_curve 56 | 57 | def main(image_path): 58 | # Load image 59 | image = cv2.imread(image_path) 60 | if image is None: 61 | print(f"Error: Unable to load image from {image_path}") 62 | return 63 | 64 | # Detect curves 65 | curves = detect_curves(image) 66 | 67 | completed_curves = [] 68 | for curve in curves: 69 | # Identify gaps 70 | gaps = identify_gaps(curve) 71 | 72 | # Complete curve 73 | if gaps: 74 | try: 75 | completed_curve = complete_curve(curve, gaps) 76 | completed_curves.append(completed_curve) 77 | except Exception as e: 78 | print(f"Error completing curve: {e}") 79 | completed_curves.append(curve) 80 | else: 81 | completed_curves.append(curve) 82 | 83 | # Draw completed curves on the image 84 | result = image.copy() 85 | cv2.drawContours(result, completed_curves, -1, (0, 255, 0), 2) 86 | 87 | # Display result 88 | cv2.imshow('Completed Curves', result) 89 | cv2.waitKey(0) 90 | cv2.destroyAllWindows() 91 | 92 | if __name__ == "__main__": 93 | main("C:\\Users\\vamsi\\OneDrive\\Desktop\\del.png") 94 | 95 | -------------------------------------------------------------------------------- /model/finalv3.py: -------------------------------------------------------------------------------- 1 | import os 2 | import cv2 3 | import json 4 | import numpy as np 5 | import pandas as pd 6 | from tensorflow.keras.utils import to_categorical 7 | import tensorflow as tf 8 | from tensorflow.keras.models import Sequential 9 | from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout 10 | import matplotlib.pyplot as plt 11 | 12 | # Function to convert drawing data to an image 13 | def json_to_image(drawing): 14 | drawing_data = json.loads(drawing) 15 | image = np.zeros((256, 256), dtype=np.uint8) 16 | for stroke in drawing_data: 17 | for i in range(len(stroke[0]) - 1): 18 | cv2.line(image, (stroke[0][i], stroke[1][i]), (stroke[0][i+1], stroke[1][i+1]), 255, 2) 19 | return image 20 | 21 | # Load dataset 22 | df = pd.read_csv('/content/doodle_dataset/master_doodle_dataframe.csv') 23 | 24 | # Map words to indices 25 | word_to_index = {word: i for i, word in enumerate(df['word'].unique())} 26 | df['label'] = df['word'].map(word_to_index) 27 | 28 | # Generator to load data in batches 29 | def data_generator(csv_file, batch_size): 30 | df = pd.read_csv(csv_file) 31 | X = [] 32 | y = [] 33 | 34 | for index, row in df.iterrows(): 35 | class_label = row['word'] 36 | label = row['label'] 37 | image_name = str(row['key_id']) + '.png' 38 | image_path = f'/content/doodle_dataset/doodle/{class_label}/{image_name}' 39 | 40 | if not os.path.exists(image_path): 41 | print(f"ERROR: File not found {image_path}") 42 | continue 43 | 44 | image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) 45 | if image is None: 46 | print(f"ERROR: Failed to read {image_path}") 47 | continue 48 | 49 | image = cv2.resize(image, (256, 256)) 50 | y.append(to_categorical(label, num_classes=340)) 51 | X.append(json_to_image(row['drawing'])) 52 | 53 | if len(X) >= batch_size: 54 | yield np.array(X).reshape(-1, 256, 256, 1) / 255.0, np.array(y) 55 | X = [] 56 | y = [] 57 | 58 | if X: # Yield remaining data 59 | yield np.array(X).reshape(-1, 256, 256, 1) / 255.0, np.array(y) 60 | 61 | # Define the model 62 | model = Sequential([ 63 | Conv2D(32, (3, 3), activation='relu', input_shape=(256, 256, 1)), 64 | MaxPooling2D((2, 2)), 65 | Conv2D(64, (3, 3), activation='relu'), 66 | MaxPooling2D((2, 2)), 67 | Conv2D(128, (3, 3), activation='relu'), 68 | MaxPooling2D((2, 2)), 69 | Flatten(), 70 | Dense(128, activation='relu'), 71 | Dropout(0.5), 72 | Dense(340, activation='softmax') 73 | ]) 74 | 75 | # Compile the model 76 | model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) 77 | 78 | # Train the model using the data generator 79 | epochs = 10 80 | steps_per_epoch = len(df) // batch_size 81 | 82 | model.fit( 83 | data_generator('/content/doodle_dataset/master_doodle_dataframe.csv', batch_size), 84 | epochs=epochs, 85 | steps_per_epoch=steps_per_epoch 86 | ) 87 | 88 | # Save the model 89 | model.save('/content/doodle_regularization_model.h5') 90 | 91 | def visualize_regularization(image, prediction): 92 | # Placeholder visualization function 93 | plt.imshow(image.squeeze(), cmap='gray') 94 | plt.title(f'Predicted: {prediction}') 95 | plt.show() 96 | 97 | # Load a test image from the generator 98 | for X_batch, y_batch in data_generator('/content/doodle_dataset/master_doodle_dataframe.csv', batch_size): 99 | test_image = X_batch[0] 100 | break 101 | 102 | # Predict 103 | prediction = model.predict(test_image[np.newaxis, ...]) 104 | predicted_class = np.argmax(prediction) 105 | 106 | # Visualize 107 | visualize_regularization(test_image, predicted_class) 108 | -------------------------------------------------------------------------------- /model/test.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | import cv2 4 | import json 5 | from sklearn.model_selection import train_test_split 6 | from tensorflow.keras.models import Sequential 7 | from tensorflow.keras.layers import Conv2D, MaxPooling2D, UpSampling2D 8 | 9 | # Load data in chunks 10 | chunksize = 1000 # Adjust this value based on your system's memory capacity 11 | df_iterator = pd.read_csv('C:\\Users\\vamsi\\OneDrive\\Desktop\\Adobe\\model\\master_doodle_dataframe.csv', chunksize=chunksize) 12 | 13 | def json_to_image(drawing_json): 14 | drawing = json.loads(drawing_json) 15 | image = np.zeros((256, 256), dtype=np.uint8) 16 | for stroke in drawing: 17 | for i in range(len(stroke[0]) - 1): 18 | cv2.line(image, (stroke[0][i], stroke[1][i]), (stroke[0][i+1], stroke[1][i+1]), 255, 2) 19 | return image 20 | 21 | def regularize_shape(image): 22 | # Edge detection 23 | edges = cv2.Canny(image, 50, 150) 24 | 25 | # Find contours 26 | contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 27 | 28 | # Create a blank image for the regularized shapes 29 | regularized = np.zeros_like(image) 30 | 31 | for contour in contours: 32 | # Simplify contour 33 | epsilon = 0.02 * cv2.arcLength(contour, True) 34 | approx = cv2.approxPolyDP(contour, epsilon, True) 35 | 36 | # Identify and draw regularized shapes 37 | if len(approx) == 3: 38 | cv2.drawContours(regularized, [approx], 0, 255, 2) # Triangle 39 | elif len(approx) == 4: 40 | cv2.drawContours(regularized, [approx], 0, 255, 2) # Rectangle/Square 41 | else: 42 | # Fit a circle or ellipse 43 | (x, y), radius = cv2.minEnclosingCircle(contour) 44 | center = (int(x), int(y)) 45 | radius = int(radius) 46 | cv2.circle(regularized, center, radius, 255, 2) 47 | 48 | return regularized 49 | 50 | # Process data in chunks 51 | X_list = [] 52 | y_list = [] 53 | 54 | for chunk in df_iterator: 55 | # Convert JSON drawings to images 56 | chunk['image'] = chunk['drawing'].apply(json_to_image) 57 | 58 | # Apply regularization to all images 59 | chunk['regularized'] = chunk['image'].apply(regularize_shape) 60 | 61 | # Append to lists 62 | X_list.extend(chunk['image'].tolist()) 63 | y_list.extend(chunk['regularized'].tolist()) 64 | 65 | print(f"Processed {len(X_list)} images so far...") 66 | 67 | # Optional: break after processing a certain number of images 68 | if len(X_list) >= 10000: # Adjust this number as needed 69 | break 70 | 71 | # Convert lists to numpy arrays 72 | X = np.array(X_list).reshape(-1, 256, 256, 1) 73 | y = np.array(y_list).reshape(-1, 256, 256, 1) 74 | 75 | # Free up memory 76 | del X_list, y_list 77 | 78 | # Split data 79 | X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) 80 | 81 | # Create a simple U-Net-like model 82 | model = Sequential([ 83 | Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(256, 256, 1)), 84 | MaxPooling2D((2, 2)), 85 | Conv2D(64, (3, 3), activation='relu', padding='same'), 86 | MaxPooling2D((2, 2)), 87 | Conv2D(64, (3, 3), activation='relu', padding='same'), 88 | UpSampling2D((2, 2)), 89 | Conv2D(32, (3, 3), activation='relu', padding='same'), 90 | UpSampling2D((2, 2)), 91 | Conv2D(1, (3, 3), activation='sigmoid', padding='same') 92 | ]) 93 | 94 | model.compile(optimizer='adam', loss='binary_crossentropy') 95 | 96 | # Train the model 97 | model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=10, batch_size=32) 98 | 99 | # Function to process new images 100 | def process_new_image(image_path): 101 | image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) 102 | image = cv2.resize(image, (256, 256)) 103 | image = image.reshape(1, 256, 256, 1) 104 | regularized = model.predict(image) 105 | return regularized.reshape(256, 256) 106 | 107 | # Example usage 108 | new_image_path = 'path_to_new_image.jpg' 109 | result = process_new_image(new_image_path) 110 | cv2.imshow('Regularized Image', result) 111 | cv2.waitKey(0) 112 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Adobe V2/test.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | import svgwrite 4 | 5 | def load_image(path): 6 | return cv2.imread(path, cv2.IMREAD_GRAYSCALE) 7 | 8 | def detect_edges(image): 9 | return cv2.Canny(image, 50, 150) 10 | 11 | def find_contours(edges): 12 | contours, _ = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 13 | return contours 14 | 15 | def approximate_contours(contours): 16 | approximations = [cv2.approxPolyDP(contour, 0.02 * cv2.arcLength(contour, True), True) for contour in contours] 17 | return approximations 18 | 19 | def classify_shapes(approximations): 20 | shapes = [] 21 | for approx in approximations: 22 | if len(approx) == 3: 23 | shapes.append(('triangle', approx)) 24 | elif len(approx) == 4: 25 | shapes.append(('quadrilateral', approx)) 26 | elif len(approx) > 10: 27 | shapes.append(('circle', approx)) 28 | else: 29 | shapes.append(('polygon', approx)) 30 | return shapes 31 | 32 | def regularize_shapes(shapes): 33 | regularized_shapes = [] 34 | for shape in shapes: 35 | if shape[0] == 'triangle': 36 | regularized_shapes.append(('triangle', regularize_triangle(shape[1]))) 37 | elif shape[0] == 'quadrilateral': 38 | regularized_shapes.append(('quadrilateral', regularize_quadrilateral(shape[1]))) 39 | elif shape[0] == 'circle': 40 | regularized_shapes.append(('circle', regularize_circle(shape[1]))) 41 | elif shape[0] == 'polygon': 42 | regularized_shapes.append(('polygon', regularize_polygon(shape[1]))) 43 | return regularized_shapes 44 | 45 | def regularize_triangle(contour): 46 | M = cv2.moments(contour) 47 | cx = int(M['m10'] / M['m00']) 48 | cy = int(M['m01'] / M['m00']) 49 | distances = [cv2.pointPolygonTest(contour, (cx, cy), True) for point in contour] 50 | avg_distance = np.mean(distances) 51 | angle = 2 * np.pi / 3 52 | regular_triangle = np.array([[cx + avg_distance * np.cos(i * angle), cy + avg_distance * np.sin(i * angle)] for i in range(3)], dtype=np.int32) 53 | return regular_triangle.reshape(-1, 1, 2) 54 | 55 | def regularize_quadrilateral(contour): 56 | rect = cv2.minAreaRect(contour) 57 | box = cv2.boxPoints(rect) 58 | return box.astype(int).reshape(-1, 1, 2) 59 | 60 | def regularize_circle(contour): 61 | center, radius = cv2.minEnclosingCircle(contour) 62 | return cv2.ellipse2Poly((int(center[0]), int(center[1])), (int(radius), int(radius)), 0, 0, 360, 1) 63 | 64 | def regularize_polygon(contour): 65 | return contour 66 | 67 | def convert_to_bezier(contour): 68 | bezier_curves = [] 69 | for i in range(len(contour) - 1): 70 | p0 = contour[i][0] 71 | p1 = contour[i + 1][0] 72 | if isinstance(p0, np.ndarray) and isinstance(p1, np.ndarray): 73 | c1 = ((p0 + p1) / 2).astype(int) # Midpoint as control point 74 | bezier_curves.append((p0, c1, p1, p1)) 75 | else: 76 | # Skip this curve if the points are not in the expected format 77 | print(f"Skipping invalid curve: {p0}, {p1}") 78 | return bezier_curves 79 | 80 | def visualize_svg(bezier_curves): 81 | dwg = svgwrite.Drawing('output.svg', profile='tiny') 82 | for curve_set in bezier_curves: 83 | for curve in curve_set: 84 | if len(curve) != 4 or any(len(point) != 2 for point in curve): 85 | print(f"Skipping invalid curve: {curve}") 86 | continue 87 | print(f"Curve: {curve}") # Debug print to check the structure 88 | path_data = "M {} {} C {} {}, {} {}, {} {}".format( 89 | curve[0][0], curve[0][1], 90 | curve[1][0], curve[1][1], 91 | curve[2][0], curve[2][1], 92 | curve[3][0], curve[3][1] 93 | ) 94 | dwg.add(dwg.path(d=path_data, fill="none", stroke="black")) 95 | dwg.save() 96 | 97 | def main(): 98 | image = load_image('ball.png') # Load input image 99 | edges = detect_edges(image) # Detect edges 100 | contours = find_contours(edges) # Find contours 101 | approximations = approximate_contours(contours) # Approximate contours 102 | shapes = classify_shapes(approximations) # Classify shapes 103 | regularized_shapes = regularize_shapes(shapes) # Regularize shapes 104 | bezier_curves = [convert_to_bezier(shape[1]) for shape in regularized_shapes] # Fit Bezier curves 105 | visualize_svg(bezier_curves) # Output results 106 | 107 | if __name__ == "_main_": 108 | main() -------------------------------------------------------------------------------- /Adobe V2/symmetry.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | from scipy.ndimage import maximum_filter 4 | 5 | sift = cv2.SIFT_create() 6 | 7 | def very_close(a, b, tol=4.0): 8 | return np.sqrt((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2) < tol 9 | 10 | def S(si, sj, sigma=1): 11 | q = (-abs(si - sj)) / (sigma * (si + sj)) 12 | return np.exp(q ** 2) 13 | 14 | def reisfeld(phi, phj, theta): 15 | return 1 - np.cos(phi + phj - 2 * theta) 16 | 17 | def midpoint(i, j): 18 | return (i[0] + j[0]) / 2, (i[1] + j[1]) / 2 19 | 20 | def angle_with_x_axis(i, j): 21 | x, y = i[0] - j[0], i[1] - j[1] 22 | if x == 0: 23 | return np.pi / 2 24 | angle = np.arctan(y / x) 25 | if angle < 0: 26 | angle += np.pi 27 | return angle 28 | 29 | def detect_symmetry(image): 30 | mimage = np.fliplr(image) 31 | kp1, des1 = sift.detectAndCompute(image, None) 32 | kp2, des2 = sift.detectAndCompute(mimage, None) 33 | for p, mp in zip(kp1, kp2): 34 | p.angle = np.deg2rad(p.angle) 35 | mp.angle = np.deg2rad(mp.angle) 36 | bf = cv2.BFMatcher() 37 | matches = bf.knnMatch(des1, des2, k=2) 38 | 39 | houghr = [] 40 | houghth = [] 41 | weights = [] 42 | 43 | for match, match2 in matches: 44 | point = kp1[match.queryIdx] 45 | mirpoint = kp2[match.trainIdx] 46 | mirpoint2 = kp2[match2.trainIdx] 47 | mirpoint2.angle = np.pi - mirpoint2.angle 48 | mirpoint.angle = np.pi - mirpoint.angle 49 | if mirpoint.angle < 0.0: 50 | mirpoint.angle += 2 * np.pi 51 | if mirpoint2.angle < 0.0: 52 | mirpoint2.angle += 2 * np.pi 53 | mirpoint.pt = (mimage.shape[1] - mirpoint.pt[0], mirpoint.pt[1]) 54 | if very_close(point.pt, mirpoint.pt): 55 | mirpoint = mirpoint2 56 | 57 | theta = angle_with_x_axis(point.pt, mirpoint.pt) 58 | xc, yc = midpoint(point.pt, mirpoint.pt) 59 | r = xc * np.cos(theta) + yc * np.sin(theta) 60 | Mij = reisfeld(point.angle, mirpoint.angle, theta) * S(point.size, mirpoint.size) 61 | 62 | houghr.append(r) 63 | houghth.append(theta) 64 | weights.append(Mij) 65 | 66 | return np.array(houghr), np.array(houghth), np.array(weights) 67 | 68 | def find_symmetry_lines(houghr, houghth, weights, threshold=0.7): 69 | H, xedges, yedges = np.histogram2d(houghr, houghth, bins=200, weights=weights) 70 | H = H / np.max(H) 71 | 72 | local_max = maximum_filter(H, size=5) 73 | detected_peaks = (H == local_max) & (H > threshold) 74 | 75 | peak_coordinates = np.argwhere(detected_peaks) 76 | r_values = xedges[peak_coordinates[:, 0]] 77 | theta_values = yedges[peak_coordinates[:, 1]] 78 | 79 | return r_values, theta_values 80 | 81 | def draw_symmetry_lines(image, r_values, theta_values): 82 | result = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR) 83 | h, w = image.shape[:2] 84 | 85 | for r, theta in zip(r_values, theta_values): 86 | a = np.cos(theta) 87 | b = np.sin(theta) 88 | x0 = a * r 89 | y0 = b * r 90 | x1 = int(x0 + 1000 * (-b)) 91 | y1 = int(y0 + 1000 * (a)) 92 | x2 = int(x0 - 1000 * (-b)) 93 | y2 = int(y0 - 1000 * (a)) 94 | 95 | if abs(theta) < 0.1 or abs(theta - np.pi) < 0.1: 96 | color = (0, 255, 0) # Green for vertical 97 | elif abs(theta - np.pi/2) < 0.1: 98 | color = (0, 0, 255) # Red for horizontal 99 | else: 100 | color = (255, 0, 0) # Blue for diagonal 101 | 102 | cv2.line(result, (x1, y1), (x2, y2), color, 2) 103 | 104 | return result 105 | 106 | def process_image(input_path, output_path): 107 | # Read the input image 108 | image = cv2.imread(input_path, 0) 109 | 110 | if image is None: 111 | print(f"Error: Unable to read the image at {input_path}") 112 | return 113 | 114 | # Detect symmetry 115 | houghr, houghth, weights = detect_symmetry(image) 116 | 117 | # Find symmetry lines 118 | r_values, theta_values = find_symmetry_lines(houghr, houghth, weights) 119 | 120 | # Draw symmetry lines on the image 121 | result = draw_symmetry_lines(image, r_values, theta_values) 122 | 123 | # Save the output image 124 | cv2.imwrite(output_path, result) 125 | print(f"Symmetry detection complete. Output saved to {output_path}") 126 | 127 | # Specify the input and output file paths directly 128 | input_path = "star.jpg" 129 | output_path = "op.png" 130 | 131 | # Process the image 132 | process_image(input_path, output_path) -------------------------------------------------------------------------------- /Adobe V2/symm2.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | from scipy.signal import convolve2d 5 | 6 | def load_image(file_path): 7 | img = cv2.imread(file_path, cv2.IMREAD_GRAYSCALE) 8 | if img is None: 9 | raise ValueError(f"Unable to load image from {file_path}") 10 | return img 11 | 12 | def preprocess_image(img): 13 | # Apply thresholding to create a binary image 14 | _, binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) 15 | # Apply edge detection 16 | edges = cv2.Canny(binary, 50, 150) 17 | return edges 18 | 19 | def check_symmetry(img, axis_type, threshold=0.95): 20 | h, w = img.shape[:2] 21 | if axis_type == "vertical": 22 | mid = w // 2 23 | left = img[:, :mid] 24 | right = cv2.flip(img[:, -mid:], 1) 25 | similarity = np.sum(left == right) / (h * mid) 26 | elif axis_type == "horizontal": 27 | mid = h // 2 28 | top = img[:mid, :] 29 | bottom = cv2.flip(img[-mid:, :], 0) 30 | similarity = np.sum(top == bottom) / (mid * w) 31 | elif axis_type == "diagonal": 32 | flipped = cv2.flip(img, -1) 33 | similarity = np.sum(img == flipped) / (h * w) 34 | return similarity > threshold 35 | def check_rotational_symmetry(img, n=3, threshold=0.95): 36 | h, w = img.shape[:2] 37 | center = (w // 2, h // 2) 38 | angle = 360 // n 39 | rot_mat = cv2.getRotationMatrix2D(center, angle, 1.0) 40 | rotated = cv2.warpAffine(img, rot_mat, (w, h)) 41 | similarity = np.sum(img == rotated) / (h * w) 42 | return similarity > threshold 43 | 44 | def draw_symmetry_line(img, axis_type): 45 | h, w = img.shape[:2] 46 | result = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) 47 | if axis_type == "vertical": 48 | cv2.line(result, (w//2, 0), (w//2, h), (0, 255, 0), 2) 49 | elif axis_type == "horizontal": 50 | cv2.line(result, (0, h//2), (w, h//2), (0, 255, 0), 2) 51 | elif axis_type == "diagonal": 52 | cv2.line(result, (0, 0), (w, h), (0, 255, 0), 2) 53 | cv2.line(result, (w, 0), (0, h), (0, 255, 0), 2) 54 | return result 55 | 56 | def draw_rotational_symmetry(img, n): 57 | h, w = img.shape[:2] 58 | result = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) 59 | center = (w // 2, h // 2) 60 | radius = min(h, w) // 4 61 | for i in range(n): 62 | angle = i * (360 / n) 63 | x = int(center[0] + radius * np.cos(np.radians(angle))) 64 | y = int(center[1] + radius * np.sin(np.radians(angle))) 65 | cv2.line(result, center, (x, y), (0, 255, 0), 2) 66 | return result 67 | 68 | def analyze_symmetry(img): 69 | preprocessed = preprocess_image(img) 70 | results = [] 71 | for axis in ["vertical", "horizontal", "diagonal"]: 72 | if check_symmetry(preprocessed, axis): 73 | img_with_line = draw_symmetry_line(img, axis) 74 | results.append((f"{axis} symmetry", img_with_line)) 75 | 76 | for n in [2, 3, 4]: # Check for 2-fold, 3-fold, and 4-fold rotational symmetry 77 | if check_rotational_symmetry(preprocessed, n): 78 | img_with_rotation = draw_rotational_symmetry(img, n) 79 | results.append((f"{n}-fold rotational symmetry", img_with_rotation)) 80 | 81 | if not results: 82 | results.append(("no symmetry detected", cv2.cvtColor(img, cv2.COLOR_GRAY2BGR))) 83 | 84 | return results 85 | 86 | def plot_results(results, original_img): 87 | n = len(results) + 1 # +1 for the original image 88 | cols = min(3, n) 89 | rows = (n + cols - 1) // cols 90 | 91 | fig, axes = plt.subplots(rows, cols, figsize=(15, 5*rows)) 92 | if rows == 1 and cols == 1: 93 | axes = [axes] 94 | else: 95 | axes = axes.flatten() 96 | 97 | # Plot original image 98 | axes[0].imshow(original_img, cmap='gray') 99 | axes[0].set_title("Original Image") 100 | axes[0].axis('off') 101 | 102 | # Plot symmetry results 103 | for i, (title, img) in enumerate(results, start=1): 104 | axes[i].imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) 105 | axes[i].set_title(title) 106 | axes[i].axis('off') 107 | 108 | for i in range(n, len(axes)): 109 | fig.delaxes(axes[i]) 110 | 111 | plt.tight_layout() 112 | plt.show() 113 | 114 | def main(image_path): 115 | # Load the image 116 | original_img = load_image(image_path) 117 | 118 | # Analyze symmetry 119 | results = analyze_symmetry(original_img) 120 | 121 | # Plot results 122 | plot_results(results, original_img) 123 | 124 | if __name__ == "__main__": 125 | image_path = 'test1.png' 126 | main(image_path) 127 | 128 | -------------------------------------------------------------------------------- /Adobe V2/tempCodeRunnerFile.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | from scipy.signal import convolve2d 5 | 6 | def load_image(file_path): 7 | img = cv2.imread(file_path, cv2.IMREAD_GRAYSCALE) 8 | if img is None: 9 | raise ValueError(f"Unable to load image from {file_path}") 10 | return img 11 | 12 | def preprocess_image(img): 13 | # Apply thresholding to create a binary image 14 | _, binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) 15 | # Apply edge detection 16 | edges = cv2.Canny(binary, 50, 150) 17 | return edges 18 | 19 | def check_symmetry(img, axis_type, threshold=0.95): 20 | h, w = img.shape[:2] 21 | if axis_type == "vertical": 22 | mid = w // 2 23 | left = img[:, :mid] 24 | right = cv2.flip(img[:, -mid:], 1) 25 | similarity = np.sum(left == right) / (h * mid) 26 | elif axis_type == "horizontal": 27 | mid = h // 2 28 | top = img[:mid, :] 29 | bottom = cv2.flip(img[-mid:, :], 0) 30 | similarity = np.sum(top == bottom) / (mid * w) 31 | elif axis_type == "diagonal": 32 | flipped = cv2.flip(img, -1) 33 | similarity = np.sum(img == flipped) / (h * w) 34 | return similarity > threshold 35 | def check_rotational_symmetry(img, n=3, threshold=0.95): 36 | h, w = img.shape[:2] 37 | center = (w // 2, h // 2) 38 | angle = 360 // n 39 | rot_mat = cv2.getRotationMatrix2D(center, angle, 1.0) 40 | rotated = cv2.warpAffine(img, rot_mat, (w, h)) 41 | similarity = np.sum(img == rotated) / (h * w) 42 | return similarity > threshold 43 | 44 | def draw_symmetry_line(img, axis_type): 45 | h, w = img.shape[:2] 46 | result = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) 47 | if axis_type == "vertical": 48 | cv2.line(result, (w//2, 0), (w//2, h), (0, 255, 0), 2) 49 | elif axis_type == "horizontal": 50 | cv2.line(result, (0, h//2), (w, h//2), (0, 255, 0), 2) 51 | elif axis_type == "diagonal": 52 | cv2.line(result, (0, 0), (w, h), (0, 255, 0), 2) 53 | cv2.line(result, (w, 0), (0, h), (0, 255, 0), 2) 54 | return result 55 | 56 | def draw_rotational_symmetry(img, n): 57 | h, w = img.shape[:2] 58 | result = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) 59 | center = (w // 2, h // 2) 60 | radius = min(h, w) // 4 61 | for i in range(n): 62 | angle = i * (360 / n) 63 | x = int(center[0] + radius * np.cos(np.radians(angle))) 64 | y = int(center[1] + radius * np.sin(np.radians(angle))) 65 | cv2.line(result, center, (x, y), (0, 255, 0), 2) 66 | return result 67 | 68 | def analyze_symmetry(img): 69 | preprocessed = preprocess_image(img) 70 | results = [] 71 | for axis in ["vertical", "horizontal", "diagonal"]: 72 | if check_symmetry(preprocessed, axis): 73 | img_with_line = draw_symmetry_line(img, axis) 74 | results.append((f"{axis} symmetry", img_with_line)) 75 | 76 | for n in [2, 3, 4]: # Check for 2-fold, 3-fold, and 4-fold rotational symmetry 77 | if check_rotational_symmetry(preprocessed, n): 78 | img_with_rotation = draw_rotational_symmetry(img, n) 79 | results.append((f"{n}-fold rotational symmetry", img_with_rotation)) 80 | 81 | if not results: 82 | results.append(("no symmetry detected", cv2.cvtColor(img, cv2.COLOR_GRAY2BGR))) 83 | 84 | return results 85 | 86 | def plot_results(results, original_img): 87 | n = len(results) + 1 # +1 for the original image 88 | cols = min(3, n) 89 | rows = (n + cols - 1) // cols 90 | 91 | fig, axes = plt.subplots(rows, cols, figsize=(15, 5*rows)) 92 | if rows == 1 and cols == 1: 93 | axes = [axes] 94 | else: 95 | axes = axes.flatten() 96 | 97 | # Plot original image 98 | axes[0].imshow(original_img, cmap='gray') 99 | axes[0].set_title("Original Image") 100 | axes[0].axis('off') 101 | 102 | # Plot symmetry results 103 | for i, (title, img) in enumerate(results, start=1): 104 | axes[i].imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) 105 | axes[i].set_title(title) 106 | axes[i].axis('off') 107 | 108 | for i in range(n, len(axes)): 109 | fig.delaxes(axes[i]) 110 | 111 | plt.tight_layout() 112 | plt.show() 113 | 114 | def main(image_path): 115 | # Load the image 116 | original_img = load_image(image_path) 117 | 118 | # Analyze symmetry 119 | results = analyze_symmetry(original_img) 120 | 121 | # Plot results 122 | plot_results(results, original_img) 123 | 124 | if __name__ == "__main__": 125 | image_path = 'rect.png' 126 | main(image_path) 127 | 128 | -------------------------------------------------------------------------------- /Adobe V2/webapp/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request, jsonify, render_template 2 | import cv2 3 | import numpy as np 4 | import base64 5 | import tempfile 6 | import os 7 | from PIL import Image 8 | import matplotlib.pyplot as plt 9 | 10 | app = Flask(__name__) 11 | 12 | def load_image(file): 13 | # Create a temporary file 14 | with tempfile.NamedTemporaryFile(delete=False, suffix='.png') as temp_file: 15 | temp_file_path = temp_file.name 16 | file.save(temp_file_path) 17 | 18 | # Load the image from the temporary file 19 | img = cv2.imread(temp_file_path, cv2.IMREAD_GRAYSCALE) 20 | if img is None: 21 | raise ValueError("Unable to load image") 22 | 23 | # Remove the temporary file after loading 24 | os.remove(temp_file_path) 25 | return img 26 | 27 | def preprocess_image(img): 28 | # Apply thresholding to create a binary image 29 | _, binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) 30 | # Apply edge detection 31 | edges = cv2.Canny(binary, 50, 150) 32 | return edges 33 | 34 | def check_symmetry(img, axis_type, threshold=0.95): 35 | h, w = img.shape[:2] 36 | if axis_type == "vertical": 37 | mid = w // 2 38 | left = img[:, :mid] 39 | right = cv2.flip(img[:, -mid:], 1) 40 | similarity = np.sum(left == right) / (h * mid) 41 | elif axis_type == "horizontal": 42 | mid = h // 2 43 | top = img[:mid, :] 44 | bottom = cv2.flip(img[-mid:, :], 0) 45 | similarity = np.sum(top == bottom) / (mid * w) 46 | elif axis_type == "diagonal": 47 | flipped = cv2.flip(img, -1) 48 | similarity = np.sum(img == flipped) / (h * w) 49 | return similarity > threshold 50 | 51 | def check_rotational_symmetry(img, n=3, threshold=0.95): 52 | h, w = img.shape[:2] 53 | center = (w // 2, h // 2) 54 | angle = 360 // n 55 | rot_mat = cv2.getRotationMatrix2D(center, angle, 1.0) 56 | rotated = cv2.warpAffine(img, rot_mat, (w, h)) 57 | similarity = np.sum(img == rotated) / (h * w) 58 | return similarity > threshold 59 | 60 | def draw_symmetry_line(img, axis_type): 61 | h, w = img.shape[:2] 62 | result = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) 63 | if axis_type == "vertical": 64 | cv2.line(result, (w//2, 0), (w//2, h), (0, 255, 0), 2) 65 | elif axis_type == "horizontal": 66 | cv2.line(result, (0, h//2), (w, h//2), (0, 255, 0), 2) 67 | elif axis_type == "diagonal": 68 | cv2.line(result, (0, 0), (w, h), (0, 255, 0), 2) 69 | cv2.line(result, (w, 0), (0, h), (0, 255, 0), 2) 70 | return result 71 | 72 | def draw_rotational_symmetry(img, n): 73 | h, w = img.shape[:2] 74 | result = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) 75 | center = (w // 2, h // 2) 76 | radius = min(h, w) // 4 77 | for i in range(n): 78 | angle = i * (360 / n) 79 | x = int(center[0] + radius * np.cos(np.radians(angle))) 80 | y = int(center[1] + radius * np.sin(np.radians(angle))) 81 | cv2.line(result, center, (x, y), (0, 255, 0), 2) 82 | return result 83 | 84 | def analyze_symmetry(img): 85 | preprocessed = preprocess_image(img) 86 | results = [] 87 | for axis in ["vertical", "horizontal", "diagonal"]: 88 | if check_symmetry(preprocessed, axis): 89 | img_with_line = draw_symmetry_line(img, axis) 90 | results.append((f"{axis.capitalize()} symmetry", img_with_line)) 91 | 92 | for n in [2, 3, 4]: # Check for 2-fold, 3-fold, and 4-fold rotational symmetry 93 | if check_rotational_symmetry(preprocessed, n): 94 | img_with_rotation = draw_rotational_symmetry(img, n) 95 | results.append((f"{n}-fold rotational symmetry", img_with_rotation)) 96 | 97 | if not results: 98 | results.append(("No symmetry detected", cv2.cvtColor(img, cv2.COLOR_GRAY2BGR))) 99 | 100 | return results 101 | 102 | def encode_image(img): 103 | _, buffer = cv2.imencode('.png', img) 104 | return base64.b64encode(buffer).decode('utf-8') 105 | 106 | @app.route('/') 107 | def index(): 108 | return render_template('index.html') 109 | 110 | @app.route('/analyze', methods=['POST']) 111 | def analyze(): 112 | if 'image' not in request.files: 113 | return jsonify({'error': 'No image provided'}), 400 114 | 115 | file = request.files['image'] 116 | 117 | try: 118 | img = load_image(file) 119 | except ValueError: 120 | return jsonify({'error': 'Invalid image'}), 400 121 | 122 | results = analyze_symmetry(img) 123 | encoded_results = [{'title': title, 'image': encode_image(img)} for title, img in results] 124 | 125 | return jsonify(encoded_results) 126 | 127 | if __name__ == '__main__': 128 | app.run(debug=True) 129 | -------------------------------------------------------------------------------- /Adobe Shape Complettion/comp.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | from scipy.interpolate import splprep, splev 4 | from scipy.spatial import distance as dist 5 | from sklearn.neighbors import NearestNeighbors 6 | import matplotlib.pyplot as plt 7 | 8 | def detect_occlusion_level(curve, occluding_shape): 9 | """Detects the level of occlusion of the curve by the occluding shape.""" 10 | curve_inside = cv2.pointPolygonTest(occluding_shape, tuple(curve[0]), False) 11 | if curve_inside >= 0: 12 | return "fully_contained" 13 | 14 | distances = [cv2.pointPolygonTest(occluding_shape, tuple(pt), False) for pt in curve] 15 | if all(dist >= 0 for dist in distances): 16 | return "fully_contained" 17 | elif any(dist >= 0 for dist in distances): 18 | return "partially_contained" 19 | else: 20 | return "disconnected" 21 | 22 | def extend_curve_on_boundary(curve, occluding_shape): 23 | """Extends the curve along the boundary of the occluding shape.""" 24 | hull = cv2.convexHull(occluding_shape) 25 | extended_curve = np.vstack((curve, hull)) 26 | extended_curve = fit_spline(extended_curve) 27 | return extended_curve 28 | 29 | def fit_spline(curve): 30 | """Fits a smooth spline to the curve.""" 31 | tck, _ = splprep(curve.T, s=0) 32 | new_points = splev(np.linspace(0, 1, 100), tck) 33 | return np.array(new_points).T 34 | 35 | def fit_bezier_curve(curve): 36 | """Fits a Bezier curve to the existing curve segments.""" 37 | # Implementing advanced Bezier curve fitting (simplified version) 38 | # More sophisticated libraries can be used for better accuracy 39 | P0, P1, P2 = curve[0], curve[len(curve)//2], curve[-1] 40 | bezier_curve = [] 41 | for t in np.linspace(0, 1, 100): 42 | point = (1-t)**2 * P0 + 2*(1-t)*t * P1 + t**2 * P2 43 | bezier_curve.append(point) 44 | return np.array(bezier_curve) 45 | 46 | def connect_disconnected_segments(curve_segments): 47 | """Connects disconnected curve segments using a graph-based approach.""" 48 | all_points = np.vstack(curve_segments) 49 | nbrs = NearestNeighbors(n_neighbors=2).fit(all_points) 50 | distances, indices = nbrs.kneighbors(all_points) 51 | 52 | graph = [] 53 | for i, (dist, idx) in enumerate(zip(distances[:,1], indices[:,1])): 54 | if dist < 50: # Threshold distance to connect points 55 | graph.append([all_points[i], all_points[idx]]) 56 | 57 | complete_curve = np.vstack(graph) 58 | return fit_spline(complete_curve) 59 | 60 | def complete_curve(curve, occluding_shape): 61 | """Main function to complete the curve based on the detected occlusion level.""" 62 | occlusion_level = detect_occlusion_level(curve, occluding_shape) 63 | 64 | if occlusion_level == "fully_contained": 65 | completed_curve = extend_curve_on_boundary(curve, occluding_shape) 66 | elif occlusion_level == "partially_contained": 67 | completed_curve = fit_bezier_curve(curve) 68 | elif occlusion_level == "disconnected": 69 | completed_curve = connect_disconnected_segments([curve]) 70 | else: 71 | completed_curve = curve 72 | 73 | return completed_curve 74 | 75 | def process_image(image_path): 76 | """Processes the input image to detect curves and occluding shapes.""" 77 | image = cv2.imread(image_path) 78 | gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 79 | 80 | # Advanced edge detection using Canny and dilation 81 | edges = cv2.Canny(gray, 50, 150) 82 | edges = cv2.dilate(edges, None, iterations=2) 83 | 84 | # Find contours with better hierarchy processing 85 | contours, hierarchy = cv2.findContours(edges, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) 86 | 87 | curves = [] 88 | shapes = [] 89 | 90 | for i, contour in enumerate(contours): 91 | if len(contour) > 20: # More precise filtering for valid curves 92 | if hierarchy[0][i][3] == -1: # External contour 93 | curves.append(contour.reshape(-1, 2)) 94 | else: 95 | shapes.append(contour.reshape(-1, 2)) 96 | 97 | return curves, shapes 98 | 99 | def main(image_path): 100 | curves, shapes = process_image(image_path) 101 | 102 | completed_curves = [] 103 | 104 | for curve in curves: 105 | for shape in shapes: 106 | completed_curve = complete_curve(curve, shape) 107 | completed_curves.append(completed_curve) 108 | 109 | # Plotting the results 110 | plt.imshow(cv2.imread(image_path)) 111 | 112 | for curve in curves: 113 | plt.plot(curve[:, 0], curve[:, 1], 'ro-', label='Original Curve') 114 | 115 | for shape in shapes: 116 | plt.plot(shape[:, 0], shape[:, 1], 'bo-', label='Occluding Shape') 117 | 118 | for completed_curve in completed_curves: 119 | plt.plot(completed_curve[:, 0], completed_curve[:, 1], 'go-', label='Completed Curve') 120 | 121 | plt.legend() 122 | plt.show() 123 | 124 | # Example usage 125 | if __name__ == "__main__": 126 | image_path = "path_to_your_image.png" # Replace with your image file path 127 | main(image_path) 128 | -------------------------------------------------------------------------------- /Test/frag2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Adobe V2/frag2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /model/model.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | import cv2 4 | import json 5 | import os 6 | import matplotlib.pyplot as plt 7 | import tensorflow as tf 8 | from tensorflow.keras.models import Model 9 | from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, UpSampling2D, concatenate 10 | from sklearn.model_selection import train_test_split 11 | import re 12 | 13 | # Ensure TensorFlow uses the GPU 14 | if not tf.test.is_gpu_available(): 15 | raise SystemError('GPU device not found') 16 | 17 | # Data Preprocessing 18 | def json_to_image(drawing_json): 19 | drawing = json.loads(drawing_json) 20 | image = np.zeros((256, 256), dtype=np.uint8) 21 | for stroke in drawing: 22 | for i in range(len(stroke[0]) - 1): 23 | cv2.line(image, (stroke[0][i], stroke[1][i]), 24 | (stroke[0][i + 1], stroke[1][i + 1]), 255, 2) 25 | return image 26 | 27 | # Load dataset 28 | df = pd.read_csv('/content/doodle_dataset/master_doodle_dataframe.csv') 29 | 30 | def data_generator(df, batch_size): 31 | while True: 32 | for i in range(0, len(df), batch_size): 33 | batch_df = df.iloc[i:i+batch_size] 34 | X = [] 35 | y = [] 36 | 37 | for _, row in batch_df.iterrows(): 38 | class_label = row['word'] 39 | image_name = str(row['key_id']) + '.png' 40 | image_path = f'/content/doodle_dataset/doodle/{class_label}/{image_name}' 41 | 42 | if not os.path.exists(image_path): 43 | print(f"ERROR: File not found {image_path}") 44 | continue 45 | 46 | image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) 47 | if image is None: 48 | print(f"ERROR: Failed to read {image_path}") 49 | continue 50 | 51 | image = cv2.resize(image, (256, 256)) 52 | y.append(image) 53 | X.append(json_to_image(row['drawing'])) 54 | 55 | yield np.array(X).reshape(-1, 256, 256, 1) / 255.0, np.array(y).reshape(-1, 256, 256, 1) / 255.0 56 | 57 | # Split the data 58 | train_df, val_df = train_test_split(df, test_size=0.2, random_state=42) 59 | 60 | # Create U-Net Model 61 | def unet(input_size=(256, 256, 1)): 62 | inputs = Input(input_size) 63 | 64 | # Encoder (Downsampling) 65 | conv1 = Conv2D(64, 3, activation='relu', padding='same')(inputs) 66 | conv1 = Conv2D(64, 3, activation='relu', padding='same')(conv1) 67 | pool1 = MaxPooling2D(pool_size=(2, 2))(conv1) 68 | 69 | conv2 = Conv2D(128, 3, activation='relu', padding='same')(pool1) 70 | conv2 = Conv2D(128, 3, activation='relu', padding='same')(conv2) 71 | pool2 = MaxPooling2D(pool_size=(2, 2))(conv2) 72 | 73 | conv3 = Conv2D(256, 3, activation='relu', padding='same')(pool2) 74 | conv3 = Conv2D(256, 3, activation='relu', padding='same')(conv3) 75 | pool3 = MaxPooling2D(pool_size=(2, 2))(conv3) 76 | 77 | # Bridge 78 | conv4 = Conv2D(512, 3, activation='relu', padding='same')(pool3) 79 | conv4 = Conv2D(512, 3, activation='relu', padding='same')(conv4) 80 | 81 | # Decoder (Upsampling) 82 | up5 = UpSampling2D(size=(2, 2))(conv4) 83 | up5 = concatenate([up5, conv3]) 84 | conv5 = Conv2D(256, 3, activation='relu', padding='same')(up5) 85 | conv5 = Conv2D(256, 3, activation='relu', padding='same')(conv5) 86 | 87 | up6 = UpSampling2D(size=(2, 2))(conv5) 88 | up6 = concatenate([up6, conv2]) 89 | conv6 = Conv2D(128, 3, activation='relu', padding='same')(up6) 90 | conv6 = Conv2D(128, 3, activation='relu', padding='same')(conv6) 91 | 92 | up7 = UpSampling2D(size=(2, 2))(conv6) 93 | up7 = concatenate([up7, conv1]) 94 | conv7 = Conv2D(64, 3, activation='relu', padding='same')(up7) 95 | conv7 = Conv2D(64, 3, activation='relu', padding='same')(conv7) 96 | 97 | outputs = Conv2D(1, 1, activation='sigmoid')(conv7) 98 | 99 | model = Model(inputs=inputs, outputs=outputs) 100 | return model 101 | 102 | model = unet() 103 | model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) 104 | 105 | # Train the Model 106 | batch_size = 32 107 | train_generator = data_generator(train_df, batch_size) 108 | val_generator = data_generator(val_df, batch_size) 109 | 110 | steps_per_epoch = len(train_df) // batch_size 111 | validation_steps = len(val_df) // batch_size 112 | 113 | with tf.device('/device:GPU:0'): # Use GPU if available 114 | history = model.fit( 115 | train_generator, 116 | steps_per_epoch=steps_per_epoch, 117 | epochs=10, 118 | validation_data=val_generator, 119 | validation_steps=validation_steps 120 | ) 121 | 122 | def process_svg_and_save_jpg(svg_file_path, output_jpg_path, model): 123 | with open(svg_file_path, 'r') as f: 124 | svg_content = f.read() 125 | 126 | image = np.zeros((256, 256), dtype=np.uint8) 127 | paths = re.findall(r'd="([^"]*)"', svg_content) 128 | 129 | for path in paths: 130 | points = np.array([tuple(map(float, p.split(','))) for p in path.split() if ',' in p]) 131 | points = (points * 256 / 100).astype(int) # Scale to 256x256 132 | cv2.polylines(image, [points], False, 255, 1) 133 | 134 | input_image = np.expand_dims(image, axis=0) 135 | input_image = np.expand_dims(input_image, axis=-1) 136 | input_image = input_image / 255.0 137 | 138 | with tf.device('/device:GPU:0'): 139 | regularized = model.predict(input_image) 140 | 141 | regularized_image = (regularized[0, :, :, 0] * 255).astype(np.uint8) 142 | 143 | plt.figure(figsize=(10, 5)) 144 | plt.subplot(1, 2, 1) 145 | plt.imshow(image, cmap='gray') 146 | plt.title('Original Image') 147 | plt.subplot(1, 2, 2) 148 | plt.imshow(regularized_image, cmap='gray') 149 | plt.title('Regularized Image') 150 | plt.show() 151 | 152 | cv2.imwrite(output_jpg_path, regularized_image) 153 | 154 | # Example Usage 155 | svg_file_path = '/content/frag1.svg' # Update with your SVG file path 156 | output_jpg_path = '/content/output.jpg' # Update with desired output JPG location 157 | process_svg_and_save_jpg(svg_file_path, output_jpg_path, model) -------------------------------------------------------------------------------- /Test/solution_adb.py: -------------------------------------------------------------------------------- 1 | import svgpathtools 2 | import numpy as np 3 | import cv2 4 | from svgpathtools import svg2paths 5 | from scipy.optimize import leastsq 6 | from sklearn.linear_model import RANSACRegressor 7 | 8 | def parse_svg(svg_file): 9 | """Parse the SVG file and extract path data.""" 10 | paths, attributes = svg2paths(svg_file) 11 | path_data = [] 12 | for path in paths: 13 | for segment in path: 14 | segment_type = type(segment).__name__ 15 | path_data.append((segment_type, segment)) 16 | return path_data 17 | 18 | def fit_line_ransac(points): 19 | """Fit a line to the given points using RANSAC.""" 20 | points = np.array(points, dtype=np.float32) 21 | if len(points) < 2: 22 | return None 23 | 24 | # Using sklearn's RANSACRegressor 25 | ransac = RANSACRegressor() 26 | X = points[:, 0].reshape(-1, 1) 27 | y = points[:, 1] 28 | ransac.fit(X, y) 29 | 30 | # Get line parameters 31 | slope = ransac.estimator_.coef_[0] 32 | intercept = ransac.estimator_.intercept_ 33 | 34 | # Calculate line points for visualization 35 | lefty = int(intercept) 36 | righty = int(slope * 512 + intercept) 37 | return ((0, lefty), (512, righty)) 38 | 39 | 40 | def fit_circle(points): 41 | """Fit a circle to the given points using least squares method.""" 42 | points = np.array(points, dtype=np.float32) 43 | if len(points) < 2: 44 | return (0, 0), 0 # Return default if not enough points 45 | 46 | # Find the circle using least squares 47 | def calc_R(xc, yc): 48 | return np.sqrt((points[:, 0] - xc)**2 + (points[:, 1] - yc)**2) 49 | 50 | def f(c): 51 | Ri = calc_R(*c) 52 | return Ri - Ri.mean() 53 | 54 | center_estimate = np.mean(points, axis=0) 55 | center, ier = leastsq(f, center_estimate) 56 | radius = calc_R(*center).mean() 57 | return (int(center[0]), int(center[1])), int(radius) 58 | 59 | def fit_ellipse(points): 60 | """Fit an ellipse to the given points using direct least squares method.""" 61 | points = np.array(points, dtype=np.float32) 62 | if len(points) < 5: 63 | return ((0, 0), (0, 0), 0) # Return default if not enough points 64 | 65 | ellipse = cv2.fitEllipse(points) 66 | return ellipse 67 | 68 | def fit_rectangle(points): 69 | """Fit a rectangle to the given points using the min area rect method.""" 70 | points = np.array(points, dtype=np.float32) 71 | if len(points) < 2: 72 | return np.zeros((4, 2), dtype=np.int32) # Return default if not enough points 73 | rect = cv2.minAreaRect(points) 74 | box = cv2.boxPoints(rect) 75 | box = np.int32(box) 76 | return box 77 | 78 | def fit_regular_polygon(points, sides): 79 | """Fit a regular polygon to the given points.""" 80 | points = np.array(points, dtype=np.float32) 81 | if len(points) < 2: 82 | return np.zeros((sides, 2), dtype=np.int32) # Return default if not enough points 83 | centroid = np.mean(points, axis=0) 84 | angles = np.linspace(0, 2 * np.pi, sides, endpoint=False) 85 | radius = np.mean(np.linalg.norm(points - centroid, axis=1)) 86 | polygon_points = [(centroid[0] + radius * np.cos(angle), centroid[1] + radius * np.sin(angle)) for angle in angles] 87 | return np.int32(polygon_points) 88 | 89 | def segment_path(path_data): 90 | """Segment the path data based on curvature changes.""" 91 | # Placeholder implementation: treat entire path as single segment 92 | segments = [path_data] 93 | return segments 94 | 95 | def regularize_path_segment(segment): 96 | """Regularize a single path segment.""" 97 | points = [] 98 | for segment_type, segment in segment: 99 | if segment_type == 'Line': 100 | points.append((segment.start.real, segment.start.imag)) 101 | points.append((segment.end.real, segment.end.imag)) 102 | elif segment_type == 'CubicBezier': 103 | points.extend([(p.real, p.imag) for p in segment.bpoints()]) 104 | elif segment_type == 'QuadraticBezier': 105 | points.extend([(p.real, p.imag) for p in segment.bpoints()]) 106 | elif segment_type == 'Arc': 107 | points.extend([(segment.start.real, segment.start.imag), (segment.end.real, segment.end.imag)]) 108 | 109 | points = np.array(points) 110 | 111 | if len(points) < 2: 112 | return None # Skip if not enough points 113 | 114 | # Fit geometric primitives 115 | line = fit_line_ransac(points) 116 | circle_center, circle_radius = fit_circle(points) 117 | ellipse = fit_ellipse(points) 118 | rectangle = fit_rectangle(points) 119 | polygon = fit_regular_polygon(points, 5) # Example with 5 sides (pentagon) 120 | 121 | return line, circle_center, circle_radius, ellipse, rectangle, polygon 122 | 123 | def visualize_regularization(image, regularized_segments): 124 | """Visualize the regularized segments on the image.""" 125 | for line, circle_center, circle_radius, ellipse, rectangle, polygon in regularized_segments: 126 | if line: 127 | # Draw line 128 | cv2.line(image, line[0], line[1], (255, 0, 0), 2) 129 | if circle_radius > 0: 130 | # Draw circle 131 | cv2.circle(image, circle_center, circle_radius, (0, 255, 0), 2) 132 | if ellipse[1][0] > 0 and ellipse[1][1] > 0: 133 | # Draw ellipse 134 | cv2.ellipse(image, ellipse, (0, 0, 255), 2) 135 | if rectangle is not None: 136 | # Draw rectangle 137 | cv2.drawContours(image, [rectangle], 0, (255, 255, 0), 2) 138 | if polygon is not None: 139 | # Draw polygon 140 | cv2.polylines(image, [polygon], isClosed=True, color=(0, 255, 255), thickness=2) 141 | 142 | def svg_to_jpg(svg_file, output_file): 143 | """Convert SVG to regularized JPG.""" 144 | path_data = parse_svg(svg_file) 145 | segments = segment_path(path_data) 146 | 147 | regularized_segments = [] 148 | for segment in segments: 149 | regularized_segment = regularize_path_segment(segment) 150 | if regularized_segment: 151 | regularized_segments.append(regularized_segment) 152 | 153 | # Create a blank image 154 | image = np.ones((512, 512, 3), np.uint8) * 255 155 | 156 | # Visualize regularization 157 | visualize_regularization(image, regularized_segments) 158 | 159 | # Save the image 160 | cv2.imwrite(output_file, image) 161 | 162 | # Usage example 163 | svg_file = 'isolated.svg' 164 | output_file = 'output.jpg' 165 | svg_to_jpg(svg_file, output_file) -------------------------------------------------------------------------------- /Adobe V2/webapp/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Image Symmetry Analyzer 7 | 8 | 9 | 10 | 11 | 12 | 79 | 80 | 81 |
82 |
83 |

84 | Image Symmetry Analyzer 85 |

86 |
87 | 91 |
92 | 96 |
97 |
98 | 99 | 176 | 177 | -------------------------------------------------------------------------------- /model/test.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import pandas as pd\n", 10 | "import numpy as np\n", 11 | "import cv2\n", 12 | "import json\n", 13 | "from sklearn.model_selection import train_test_split\n", 14 | "from tensorflow.keras.models import Sequential\n", 15 | "from tensorflow.keras.layers import Conv2D, MaxPooling2D, UpSampling2D" 16 | ] 17 | }, 18 | { 19 | "cell_type": "code", 20 | "execution_count": 2, 21 | "metadata": {}, 22 | "outputs": [], 23 | "source": [ 24 | "# Load and preprocess data\n", 25 | "chunksize = 1000 # Adjust this value based on your system's memory capacity\n", 26 | "df = pd.read_csv('master_doodle_dataframe.csv')" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 3, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [ 35 | "def json_to_image(drawing_json):\n", 36 | " drawing = json.loads(drawing_json)\n", 37 | " image = np.zeros((256, 256), dtype=np.uint8)\n", 38 | " for stroke in drawing:\n", 39 | " for i in range(len(stroke[0]) - 1):\n", 40 | " cv2.line(image, (stroke[0][i], stroke[1][i]), (stroke[0][i+1], stroke[1][i+1]), 255, 2)\n", 41 | " return image\n" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": null, 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "def regularize_shape(image):\n", 51 | " # Edge detection\n", 52 | " edges = cv2.Canny(image, 50, 150)\n", 53 | " \n", 54 | " # Find contours\n", 55 | " contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n", 56 | " \n", 57 | " # Create a blank image for the regularized shapes\n", 58 | " regularized = np.zeros_like(image)\n", 59 | " \n", 60 | " for contour in contours:\n", 61 | " # Simplify contour\n", 62 | " epsilon = 0.02 * cv2.arcLength(contour, True)\n", 63 | " approx = cv2.approxPolyDP(contour, epsilon, True)\n", 64 | " \n", 65 | " # Identify and draw regularized shapes\n", 66 | " if len(approx) == 3:\n", 67 | " cv2.drawContours(regularized, [approx], 0, 255, 2) # Triangle\n", 68 | " elif len(approx) == 4:\n", 69 | " cv2.drawContours(regularized, [approx], 0, 255, 2) # Rectangle/Square\n", 70 | " else:\n", 71 | " # Fit a circle or ellipse\n", 72 | " (x, y), radius = cv2.minEnclosingCircle(contour)\n", 73 | " center = (int(x), int(y))\n", 74 | " radius = int(radius)\n", 75 | " cv2.circle(regularized, center, radius, 255, 2)\n", 76 | " \n", 77 | " return regularized" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": null, 83 | "metadata": {}, 84 | "outputs": [], 85 | "source": [ 86 | "# Process data in chunks\n", 87 | "X_list = []\n", 88 | "y_list = []" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": null, 94 | "metadata": {}, 95 | "outputs": [], 96 | "source": [ 97 | "for chunk in df_iterator:\n", 98 | " # Convert JSON drawings to images\n", 99 | " chunk['image'] = chunk['drawing'].apply(json_to_image)\n", 100 | " \n", 101 | " # Apply regularization to all images\n", 102 | " chunk['regularized'] = chunk['image'].apply(regularize_shape)\n", 103 | " \n", 104 | " # Append to lists\n", 105 | " X_list.extend(chunk['image'].tolist())\n", 106 | " y_list.extend(chunk['regularized'].tolist())\n", 107 | " \n", 108 | " print(f\"Processed {len(X_list)} images so far...\")\n", 109 | "\n", 110 | " # Optional: break after processing a certain number of images\n", 111 | " if len(X_list) >= 10000: # Adjust this number as needed\n", 112 | " break" 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": null, 118 | "metadata": {}, 119 | "outputs": [], 120 | "source": [ 121 | "# Prepare data for the model\n", 122 | "X = np.array(df['image'].tolist()).reshape(-1, 256, 256, 1)\n", 123 | "y = np.array(df['regularized'].tolist()).reshape(-1, 256, 256, 1)\n", 124 | "\n", 125 | "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": null, 131 | "metadata": {}, 132 | "outputs": [], 133 | "source": [ 134 | "# Create a simple U-Net-like model\n", 135 | "model = Sequential([\n", 136 | " Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(256, 256, 1)),\n", 137 | " MaxPooling2D((2, 2)),\n", 138 | " Conv2D(64, (3, 3), activation='relu', padding='same'),\n", 139 | " MaxPooling2D((2, 2)),\n", 140 | " Conv2D(64, (3, 3), activation='relu', padding='same'),\n", 141 | " UpSampling2D((2, 2)),\n", 142 | " Conv2D(32, (3, 3), activation='relu', padding='same'),\n", 143 | " UpSampling2D((2, 2)),\n", 144 | " Conv2D(1, (3, 3), activation='sigmoid', padding='same')\n", 145 | "])\n", 146 | "\n", 147 | "model.compile(optimizer='adam', loss='binary_crossentropy')" 148 | ] 149 | }, 150 | { 151 | "cell_type": "code", 152 | "execution_count": null, 153 | "metadata": {}, 154 | "outputs": [], 155 | "source": [ 156 | "# Train the model\n", 157 | "model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=10, batch_size=32)" 158 | ] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "execution_count": null, 163 | "metadata": {}, 164 | "outputs": [], 165 | "source": [ 166 | "# Function to process new images\n", 167 | "def process_new_image(image_path):\n", 168 | " image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)\n", 169 | " image = cv2.resize(image, (256, 256))\n", 170 | " image = image.reshape(1, 256, 256, 1)\n", 171 | " regularized = model.predict(image)\n", 172 | " return regularized.reshape(256, 256)\n" 173 | ] 174 | }, 175 | { 176 | "cell_type": "code", 177 | "execution_count": null, 178 | "metadata": {}, 179 | "outputs": [], 180 | "source": [ 181 | "# Example usage\n", 182 | "new_image_path = 'path_to_new_image.jpg'\n", 183 | "result = process_new_image(new_image_path)\n", 184 | "cv2.imshow('Regularized Image', result)\n", 185 | "cv2.waitKey(0)\n", 186 | "cv2.destroyAllWindows()" 187 | ] 188 | } 189 | ], 190 | "metadata": { 191 | "kernelspec": { 192 | "display_name": "Python 3", 193 | "language": "python", 194 | "name": "python3" 195 | }, 196 | "language_info": { 197 | "codemirror_mode": { 198 | "name": "ipython", 199 | "version": 3 200 | }, 201 | "file_extension": ".py", 202 | "mimetype": "text/x-python", 203 | "name": "python", 204 | "nbconvert_exporter": "python", 205 | "pygments_lexer": "ipython3", 206 | "version": "3.12.4" 207 | } 208 | }, 209 | "nbformat": 4, 210 | "nbformat_minor": 2 211 | } 212 | -------------------------------------------------------------------------------- /Adobe V2/test_indra.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | from scipy.ndimage import maximum_filter 4 | 5 | sift = cv2.SIFT_create() 6 | 7 | def very_close(a, b, tol=4.0): 8 | return np.sqrt((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2) < tol 9 | 10 | def S(si, sj, sigma=1): 11 | q = (-abs(si - sj)) / (sigma * (si + sj)) 12 | return np.exp(q ** 2) 13 | 14 | def reisfeld(phi, phj, theta): 15 | return 1 - np.cos(phi + phj - 2 * theta) 16 | 17 | def midpoint(i, j): 18 | return (i[0] + j[0]) / 2, (i[1] + j[1]) / 2 19 | 20 | def angle_with_x_axis(i, j): 21 | x, y = i[0] - j[0], i[1] - j[1] 22 | if x == 0: 23 | return np.pi / 2 24 | angle = np.arctan2(y, x) 25 | if angle < 0: 26 | angle += np.pi 27 | return angle 28 | 29 | def detect_symmetry(image): 30 | mimage = np.fliplr(image) 31 | kp1, des1 = sift.detectAndCompute(image, None) 32 | kp2, des2 = sift.detectAndCompute(mimage, None) 33 | 34 | for p, mp in zip(kp1, kp2): 35 | p.angle = np.deg2rad(p.angle) 36 | mp.angle = np.deg2rad(mp.angle) 37 | 38 | bf = cv2.BFMatcher() 39 | matches = bf.knnMatch(des1, des2, k=2) 40 | 41 | houghr = [] 42 | houghth = [] 43 | weights = [] 44 | 45 | for match, match2 in matches: 46 | if match.distance < 0.75 * match2.distance: 47 | point = kp1[match.queryIdx] 48 | mirpoint = kp2[match.trainIdx] 49 | mirpoint2 = kp2[match2.trainIdx] 50 | 51 | mirpoint2.angle = np.pi - mirpoint2.angle 52 | mirpoint.angle = np.pi - mirpoint.angle 53 | if mirpoint.angle < 0.0: 54 | mirpoint.angle += 2 * np.pi 55 | if mirpoint2.angle < 0.0: 56 | mirpoint2.angle += 2 * np.pi 57 | 58 | mirpoint.pt = (mimage.shape[1] - mirpoint.pt[0], mirpoint.pt[1]) 59 | if very_close(point.pt, mirpoint.pt): 60 | mirpoint = mirpoint2 61 | 62 | theta = angle_with_x_axis(point.pt, mirpoint.pt) 63 | xc, yc = midpoint(point.pt, mirpoint.pt) 64 | r = xc * np.cos(theta) + yc * np.sin(theta) 65 | Mij = reisfeld(point.angle, mirpoint.angle, theta) * S(point.size, mirpoint.size) 66 | 67 | houghr.append(r) 68 | houghth.append(theta) 69 | weights.append(Mij) 70 | 71 | return np.array(houghr), np.array(houghth), np.array(weights) 72 | 73 | def find_symmetry_lines(houghr, houghth, weights, threshold=0.7): 74 | H, xedges, yedges = np.histogram2d(houghr, houghth, bins=200, weights=weights) 75 | H = H / np.max(H) 76 | 77 | local_max = maximum_filter(H, size=5) 78 | detected_peaks = (H == local_max) & (H > threshold) 79 | 80 | peak_coordinates = np.argwhere(detected_peaks) 81 | r_values = xedges[peak_coordinates[:, 0]] 82 | theta_values = yedges[peak_coordinates[:, 1]] 83 | 84 | filtered_weights = [] 85 | for coord in peak_coordinates: 86 | r_idx, theta_idx = coord 87 | filtered_weights.append(H[r_idx, theta_idx]) 88 | 89 | return r_values, theta_values, np.array(filtered_weights) 90 | 91 | 92 | def select_best_symmetry(r_values, theta_values, weights): 93 | symmetries = {'vertical': None, 'horizontal': None, 'diagonal': None} 94 | 95 | for r, theta, weight in zip(r_values, theta_values, weights): 96 | if abs(theta) < 0.1 or abs(theta - np.pi) < 0.1: 97 | key = 'vertical' 98 | elif abs(theta - np.pi/2) < 0.1: 99 | key = 'horizontal' 100 | else: 101 | key = 'diagonal' 102 | 103 | if symmetries[key] is None or weight > symmetries[key][2]: 104 | symmetries[key] = (r, theta, weight) 105 | 106 | return symmetries 107 | 108 | def draw_symmetry_lines(image, symmetries): 109 | results = [] 110 | h, w = image.shape[:2] 111 | 112 | for key, sym in symmetries.items(): 113 | if sym is None: 114 | continue 115 | 116 | r, theta, _ = sym 117 | a = np.cos(theta) 118 | b = np.sin(theta) 119 | x0 = a * r 120 | y0 = b * r 121 | x1 = int(x0 + 1000 * (-b)) 122 | y1 = int(y0 + 1000 * (a)) 123 | x2 = int(x0 - 1000 * (-b)) 124 | y2 = int(y0 - 1000 * (a)) 125 | 126 | result = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR) 127 | 128 | if key == 'vertical': 129 | color = (0, 255, 0) # Green for vertical symmetry 130 | symmetry_type = "Vertical" 131 | elif key == 'horizontal': 132 | color = (0, 0, 255) # Red for horizontal symmetry 133 | symmetry_type = "Horizontal" 134 | else: 135 | color = (255, 0, 0) # Blue for diagonal symmetry 136 | symmetry_type = "Diagonal" 137 | 138 | cv2.line(result, (x1, y1), (x2, y2), color, 2) 139 | results.append((result, symmetry_type)) 140 | 141 | return results 142 | 143 | def process_image(input_path): 144 | # Read the input image 145 | image = cv2.imread(input_path, 0) 146 | 147 | if image is None: 148 | print(f"Error: Unable to read the image at {input_path}") 149 | return None 150 | 151 | # Detect symmetry 152 | houghr, houghth, weights = detect_symmetry(image) 153 | 154 | # Find symmetry lines 155 | r_values, theta_values, filtered_weights = find_symmetry_lines(houghr, houghth, weights) 156 | 157 | if len(r_values) == 0: 158 | print(f"No symmetry detected in {input_path}.") 159 | return None 160 | else: 161 | print(f"Symmetry detected in {input_path}.") 162 | # Select the best symmetry lines for each type 163 | symmetries = select_best_symmetry(r_values, theta_values, filtered_weights) 164 | 165 | # Draw symmetry lines on the image 166 | results = draw_symmetry_lines(image, symmetries) 167 | return results 168 | 169 | def display_symmetries(input_path): 170 | processed_results = process_image(input_path) 171 | 172 | if not processed_results: 173 | return 174 | 175 | # Determine the size of each cell in the grid 176 | cell_height = max(img.shape[0] for img, _ in processed_results) 177 | cell_width = max(img.shape[1] for img, _ in processed_results) 178 | 179 | # Create a blank canvas for the grid 180 | canvas_height = len(processed_results) * cell_height 181 | canvas_width = cell_width 182 | canvas = np.zeros((canvas_height, canvas_width, 3), dtype=np.uint8) 183 | 184 | # Place each processed image in the grid 185 | for i, (img, sym_type) in enumerate(processed_results): 186 | y_offset = i * cell_height 187 | canvas[y_offset:y_offset+img.shape[0], :img.shape[1]] = img 188 | cv2.putText(canvas, sym_type, (10, y_offset + 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA) 189 | 190 | # Display the combined image 191 | cv2.imshow('Symmetry Detection', canvas) 192 | cv2.waitKey(0) 193 | cv2.destroyAllWindows() 194 | 195 | # Specify the input image path 196 | input_path = "image.png" # Replace with your actual image path 197 | 198 | # Display symmetries in the image 199 | display_symmetries(input_path) -------------------------------------------------------------------------------- /model/finalv1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "# Google Colab setup\n", 10 | "!pip install opencv-python-headless\n", 11 | "!pip install tensorflow\n", 12 | "!pip install kaggle\n", 13 | "!pip install cairosvg\n", 14 | "!pip install pandas" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": null, 20 | "metadata": {}, 21 | "outputs": [], 22 | "source": [ 23 | "import pandas as pd\n", 24 | "import numpy as np\n", 25 | "import cv2\n", 26 | "import json\n", 27 | "import os\n", 28 | "import matplotlib.pyplot as plt\n", 29 | "import tensorflow as tf\n", 30 | "from tensorflow.keras.models import Model\n", 31 | "from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, UpSampling2D, concatenate\n", 32 | "from sklearn.model_selection import train_test_split\n", 33 | "import re" 34 | ] 35 | }, 36 | { 37 | "cell_type": "code", 38 | "execution_count": null, 39 | "metadata": {}, 40 | "outputs": [], 41 | "source": [ 42 | "!mkdir -p ~/.kaggle\n", 43 | "!cp /content/kaggle.json ~/.kaggle/\n", 44 | "!chmod 600 ~/.kaggle/kaggle.json\n" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": null, 50 | "metadata": {}, 51 | "outputs": [], 52 | "source": [ 53 | "# Ensure TensorFlow uses the GPU\n", 54 | "if not tf.test.is_gpu_available():\n", 55 | " raise SystemError('GPU device not found')\n" 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": null, 61 | "metadata": {}, 62 | "outputs": [], 63 | "source": [ 64 | "# Download and unzip the dataset\n", 65 | "!kaggle datasets download -d ashishjangra27/doodle-dataset\n", 66 | "!unzip doodle-dataset.zip -d /content/doodle_dataset\n" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": null, 72 | "metadata": {}, 73 | "outputs": [], 74 | "source": [ 75 | "# Data Preprocessing\n", 76 | "def json_to_image(drawing_json):\n", 77 | " drawing = json.loads(drawing_json)\n", 78 | " image = np.zeros((256, 256), dtype=np.uint8)\n", 79 | " for stroke in drawing:\n", 80 | " for i in range(len(stroke[0]) - 1):\n", 81 | " cv2.line(image, (stroke[0][i], stroke[1][i]),\n", 82 | " (stroke[0][i + 1], stroke[1][i + 1]), 255, 2)\n", 83 | " return image\n" 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": null, 89 | "metadata": {}, 90 | "outputs": [], 91 | "source": [ 92 | "\n", 93 | "# Load dataset\n", 94 | "df = pd.read_csv('/content/doodle_dataset/master_doodle_dataframe.csv')" 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": null, 100 | "metadata": {}, 101 | "outputs": [], 102 | "source": [ 103 | "def data_generator(df, batch_size):\n", 104 | " while True:\n", 105 | " for i in range(0, len(df), batch_size):\n", 106 | " batch_df = df.iloc[i:i+batch_size]\n", 107 | " X = []\n", 108 | " y = []\n", 109 | " \n", 110 | " for _, row in batch_df.iterrows():\n", 111 | " class_label = row['word']\n", 112 | " image_name = str(row['key_id']) + '.png'\n", 113 | " image_path = f'/content/doodle_dataset/doodle/{class_label}/{image_name}'\n", 114 | "\n", 115 | " if not os.path.exists(image_path):\n", 116 | " print(f\"ERROR: File not found {image_path}\")\n", 117 | " continue\n", 118 | "\n", 119 | " image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)\n", 120 | " if image is None:\n", 121 | " print(f\"ERROR: Failed to read {image_path}\")\n", 122 | " continue\n", 123 | "\n", 124 | " image = cv2.resize(image, (256, 256))\n", 125 | " y.append(image)\n", 126 | " X.append(json_to_image(row['drawing']))\n", 127 | "\n", 128 | " yield np.array(X).reshape(-1, 256, 256, 1) / 255.0, np.array(y).reshape(-1, 256, 256, 1) / 255.0\n", 129 | "\n", 130 | "# Split the data\n", 131 | "train_df, val_df = train_test_split(df, test_size=0.2, random_state=42)\n" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "execution_count": null, 137 | "metadata": {}, 138 | "outputs": [], 139 | "source": [ 140 | "# Create U-Net Model\n", 141 | "def unet(input_size=(256, 256, 1)):\n", 142 | " inputs = Input(input_size)\n", 143 | "\n", 144 | " # Encoder (Downsampling)\n", 145 | " conv1 = Conv2D(64, 3, activation='relu', padding='same')(inputs)\n", 146 | " conv1 = Conv2D(64, 3, activation='relu', padding='same')(conv1)\n", 147 | " pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)\n", 148 | "\n", 149 | " conv2 = Conv2D(128, 3, activation='relu', padding='same')(pool1)\n", 150 | " conv2 = Conv2D(128, 3, activation='relu', padding='same')(conv2)\n", 151 | " pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)\n", 152 | "\n", 153 | " conv3 = Conv2D(256, 3, activation='relu', padding='same')(pool2)\n", 154 | " conv3 = Conv2D(256, 3, activation='relu', padding='same')(conv3)\n", 155 | " pool3 = MaxPooling2D(pool_size=(2, 2))(conv3)\n", 156 | "\n", 157 | " # Bridge\n", 158 | " conv4 = Conv2D(512, 3, activation='relu', padding='same')(pool3)\n", 159 | " conv4 = Conv2D(512, 3, activation='relu', padding='same')(conv4)\n", 160 | "\n", 161 | " # Decoder (Upsampling)\n", 162 | " up5 = UpSampling2D(size=(2, 2))(conv4)\n", 163 | " up5 = concatenate([up5, conv3])\n", 164 | " conv5 = Conv2D(256, 3, activation='relu', padding='same')(up5)\n", 165 | " conv5 = Conv2D(256, 3, activation='relu', padding='same')(conv5)\n", 166 | "\n", 167 | " up6 = UpSampling2D(size=(2, 2))(conv5)\n", 168 | " up6 = concatenate([up6, conv2])\n", 169 | " conv6 = Conv2D(128, 3, activation='relu', padding='same')(up6)\n", 170 | " conv6 = Conv2D(128, 3, activation='relu', padding='same')(conv6)\n", 171 | "\n", 172 | " up7 = UpSampling2D(size=(2, 2))(conv6)\n", 173 | " up7 = concatenate([up7, conv1])\n", 174 | " conv7 = Conv2D(64, 3, activation='relu', padding='same')(up7)\n", 175 | " conv7 = Conv2D(64, 3, activation='relu', padding='same')(conv7)\n", 176 | "\n", 177 | " outputs = Conv2D(1, 1, activation='sigmoid')(conv7)\n", 178 | "\n", 179 | " model = Model(inputs=inputs, outputs=outputs)\n", 180 | " return model\n", 181 | "\n", 182 | "model = unet()\n", 183 | "model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])\n" 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": null, 189 | "metadata": {}, 190 | "outputs": [], 191 | "source": [ 192 | "# Train the Model\n", 193 | "batch_size = 32\n", 194 | "train_generator = data_generator(train_df, batch_size)\n", 195 | "val_generator = data_generator(val_df, batch_size)\n", 196 | "\n", 197 | "steps_per_epoch = len(train_df) // batch_size\n", 198 | "validation_steps = len(val_df) // batch_size\n", 199 | "\n", 200 | "with tf.device('/device:GPU:0'): # Use GPU if available\n", 201 | " history = model.fit(\n", 202 | " train_generator,\n", 203 | " steps_per_epoch=steps_per_epoch,\n", 204 | " epochs=10,\n", 205 | " validation_data=val_generator,\n", 206 | " validation_steps=validation_steps\n", 207 | " )" 208 | ] 209 | }, 210 | { 211 | "cell_type": "code", 212 | "execution_count": null, 213 | "metadata": {}, 214 | "outputs": [], 215 | "source": [ 216 | "def process_svg_and_save_jpg(svg_file_path, output_jpg_path, model):\n", 217 | " with open(svg_file_path, 'r') as f:\n", 218 | " svg_content = f.read()\n", 219 | " \n", 220 | " image = np.zeros((256, 256), dtype=np.uint8)\n", 221 | " paths = re.findall(r'd=\"([^\"]*)\"', svg_content)\n", 222 | " \n", 223 | " for path in paths:\n", 224 | " points = np.array([tuple(map(float, p.split(','))) for p in path.split() if ',' in p])\n", 225 | " points = (points * 256 / 100).astype(int) # Scale to 256x256\n", 226 | " cv2.polylines(image, [points], False, 255, 1)\n", 227 | " \n", 228 | " input_image = np.expand_dims(image, axis=0)\n", 229 | " input_image = np.expand_dims(input_image, axis=-1)\n", 230 | " input_image = input_image / 255.0\n", 231 | " \n", 232 | " with tf.device('/device:GPU:0'):\n", 233 | " regularized = model.predict(input_image)\n", 234 | " \n", 235 | " regularized_image = (regularized[0, :, :, 0] * 255).astype(np.uint8)\n", 236 | " \n", 237 | " plt.figure(figsize=(10, 5))\n", 238 | " plt.subplot(1, 2, 1)\n", 239 | " plt.imshow(image, cmap='gray')\n", 240 | " plt.title('Original Image')\n", 241 | " plt.subplot(1, 2, 2)\n", 242 | " plt.imshow(regularized_image, cmap='gray')\n", 243 | " plt.title('Regularized Image')\n", 244 | " plt.show()\n", 245 | " \n", 246 | " cv2.imwrite(output_jpg_path, regularized_image)" 247 | ] 248 | }, 249 | { 250 | "cell_type": "code", 251 | "execution_count": null, 252 | "metadata": {}, 253 | "outputs": [], 254 | "source": [ 255 | "# Example Usage\n", 256 | "svg_file_path = '/content/frag1.svg' # Update with your SVG file path\n", 257 | "output_jpg_path = '/content/output.jpg' # Update with desired output JPG location\n", 258 | "process_svg_and_save_jpg(svg_file_path, output_jpg_path, model)" 259 | ] 260 | } 261 | ], 262 | "metadata": { 263 | "language_info": { 264 | "name": "python" 265 | } 266 | }, 267 | "nbformat": 4, 268 | "nbformat_minor": 2 269 | } 270 | -------------------------------------------------------------------------------- /Test/bezier_control_points.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "path": "C 122.883,4.443 122.26,4.685 121.642,4.885999999999999 C 112.018,8.017 102.353,11.017 92.716,14.107 C 89.645,15.091999999999999 86.57799999999999,16.095 83.485,17.016 C 82.651,17.264 81.821,17.589 81.08,18.08" 4 | }, 5 | { 6 | "path": "C 53.526,101.43900000000001 51.043,101.80000000000001 48.673,102.415 C 40.709,104.48 32.763000000000005,106.613 24.8,108.682 C 21.279,109.59700000000001 17.772000000000002,110.56700000000001 14.24,111.441" 7 | }, 8 | { 9 | "path": "C 41.494,13.482 41.992,14.366999999999999 42.458999999999996,15.189 C 44.123,18.116 45.593999999999994,21.145 47.257999999999996,24.07 C 47.910999999999994,25.219 48.288999999999994,26.445 48.727999999999994,27.698 C 49.05,27.819 49.401999999999994,27.996 49.67699999999999,28.055 C 52.818999999999996,35.508 57.419999999999995,42.093 60.397999999999996,49.482 C 60.63099999999999,49.897999999999996 61.13999999999999,49.881 61.462999999999994,50.096 C 64.383,57.20399999999999 68.853,63.498999999999995 71.67599999999999,70.603 C 71.91099999999999,71.018 72.41999999999999,71.0 72.68099999999998,71.175 C 75.91299999999998,78.622 80.39799999999998,85.322 83.54099999999998,92.69 C 83.81499999999998,93.05 84.32399999999998,93.033 84.74099999999999,93.368 C 85.39899999999999,96.26899999999999 87.17499999999998,98.713 88.53099999999999,101.35499999999999 C 90.47699999999999,105.14299999999999 92.523,108.87899999999999 94.52499999999999,112.63799999999999 C 94.92899999999999,113.39699999999999 94.93199999999999,114.261 95.24499999999999,115.04599999999999 C 95.63,115.351 96.13099999999999,115.416 96.58399999999999,115.66399999999999 C 97.71799999999999,119.43599999999999 99.93999999999998,122.71599999999998 101.75699999999999,126.18199999999999 C 104.66499999999999,131.72799999999998 107.64599999999999,137.238 110.59599999999999,142.76299999999998 C 111.725,144.878 112.81499999999998,147.01899999999998 113.99999999999999,149.09799999999998 C 114.71399999999998,150.35 115.02699999999999,151.57399999999998 114.91999999999999,152.96099999999998" 10 | }, 11 | { 12 | "path": "C 157.953,89.467 157.772,89.053 157.524,88.63799999999999 C 155.63400000000001,85.46699999999998 153.821,82.25099999999999 151.991,79.04499999999999 C 151.46300000000002,78.11899999999999 151.014,77.16899999999998 150.76700000000002,76.26599999999999 C 150.36900000000003,75.78299999999999 149.86,75.8 149.52400000000003,75.576 C 144.85200000000003,77.38199999999999 139.96400000000003,78.297 135.19500000000002,79.61999999999999 C 129.61400000000003,81.16799999999999 123.98600000000002,82.54299999999999 118.39800000000002,84.07 C 117.55200000000002,84.30099999999999 116.80600000000003,84.73299999999999 116.00100000000002,85.041" 13 | }, 14 | { 15 | "path": "C 133.89000000000001,54.569 130.875,54.948 128.0,55.761 C 121.1,57.713 114.176,59.579 107.245,61.419000000000004 C 106.232,61.688 105.25200000000001,62.133 104.36,62.720000000000006" 16 | }, 17 | { 18 | "path": "C 122.803,34.839999999999996 120.233,35.083999999999996 117.795,35.701 C 110.685,37.5 103.583,39.335 96.443,41.015 C 95.485,41.24 94.673,41.866 93.79899999999999,42.32" 19 | }, 20 | { 21 | "path": "C 89.857,42.992 86.976,43.384 84.196,44.106 C 77.689,45.796 71.151,47.364000000000004 64.63499999999999,49.023 C 63.56699999999999,49.295 62.60499999999999,49.754000000000005 61.63899999999999,50.24" 22 | }, 23 | { 24 | "path": "C 124.908,109.366 122.49900000000001,109.598 120.19200000000001,110.083 C 113.42800000000001,111.507 106.70200000000001,113.102 99.92200000000001,114.451 C 98.772,114.67999999999999 97.66900000000001,115.098 96.68,115.75999999999999" 25 | }, 26 | { 27 | "path": "C 114.144,81.9 112.705,79.549 111.433,77.124 C 109.272,73.00399999999999 107.188,68.845 104.983,64.74799999999999 C 104.45400000000001,63.76399999999999 104.617,62.36099999999999 103.221,62.08099999999999 C 102.283,58.85599999999999 100.49600000000001,56.12999999999999 99.04400000000001,53.258999999999986 C 97.61600000000001,50.43499999999999 96.177,47.609999999999985 94.64200000000001,44.83999999999999 C 94.22600000000001,44.08899999999999 94.117,43.22799999999999 93.80600000000001,42.43899999999999 C 93.57300000000001,41.91299999999999 92.94100000000002,42.059999999999995 92.561,41.681999999999995 C 91.62400000000001,38.163 89.509,35.145999999999994 87.902,31.889999999999993 C 86.09,28.21699999999999 84.116,24.623999999999995 82.257,20.972999999999992 C 81.756,19.98899999999999 81.378,18.970999999999993 80.97500000000001,17.987999999999992 C 80.48,17.64999999999999 79.97300000000001,17.638999999999992 79.52600000000001,17.967999999999993 C 78.58500000000001,18.661999999999992 77.486,18.939999999999994 76.40200000000002,19.285999999999994 C 68.60500000000002,21.773999999999994 60.80600000000001,24.258999999999993 52.99900000000002,26.716999999999995 C 51.89400000000002,27.064999999999994 50.89200000000002,27.619999999999994 49.88000000000002,28.160999999999994" 28 | }, 29 | { 30 | "path": "C 99.694,63.921 95.93900000000001,64.423 92.35600000000001,65.468 C 86.70100000000001,67.117 80.98400000000001,68.543 75.316,70.147 C 74.422,70.4 73.668,70.857 72.92,71.36" 31 | }, 32 | { 33 | "path": "C 135.154,122.76299999999999 132.564,117.59599999999999 129.804,112.518 C 129.184,111.378 128.63,110.20400000000001 128.399,108.905 C 128.133,108.393 127.501,108.539 127.133,108.174 C 126.145,104.662 124.11699999999999,101.60300000000001 122.46799999999999,98.367 C 120.722,94.94 119.014,91.492 117.10199999999999,88.14800000000001 C 116.58099999999999,87.23700000000001 116.326,86.17300000000002 116.00099999999999,85.13700000000001 C 115.53699999999999,84.79300000000002 115.06799999999998,84.52600000000001 114.43799999999999,84.79600000000002 C 110.81599999999999,86.35300000000002 106.92799999999998,86.99100000000001 103.15599999999999,88.02800000000002 C 97.97399999999999,89.45300000000002 92.77199999999999,90.80700000000002 87.56299999999999,92.13600000000002 C 86.59599999999999,92.38300000000002 85.69699999999999,92.87100000000002 84.79899999999999,93.32100000000003" 34 | }, 35 | { 36 | "path": "C 68.67399999999999,72.21300000000001 65.46199999999999,72.754 62.35799999999999,73.632 C 57.24999999999999,75.07600000000001 52.11299999999999,76.41300000000001 46.99899999999999,77.837 C 46.10799999999999,78.08500000000001 45.31899999999999,78.558 44.46799999999999,78.93900000000001 C 43.91999999999999,78.82300000000001 43.45299999999999,78.48700000000001 42.93899999999999,78.325 C 42.52799999999999,76.11200000000001 41.22999999999999,74.312 40.129999999999995,72.458 C 37.714999999999996,68.386 35.43899999999999,64.234 32.974,60.192 C 32.562,59.516 32.379,58.713 32.205,57.876 C 31.845,57.407999999999994 31.205,57.349999999999994 30.683,57.074 C 26.548000000000002,58.977 22.043,59.58 17.709,60.76 C 12.657,62.135999999999996 7.552,63.329 2.478999999999999,64.63499999999999 C 2.3289999999999993,64.67399999999999 2.1599999999999993,64.63999999999999 1.9999999999999991,64.63999999999999" 37 | }, 38 | { 39 | "path": "C 44.933,29.618000000000002 40.977000000000004,30.491 37.154,31.743000000000002 C 32.454,33.282000000000004 27.752000000000002,34.823 23.006000000000004,36.222 C 22.075000000000003,36.497 21.209000000000003,37.02 20.359000000000005,37.52" 40 | }, 41 | { 42 | "path": "C 57.269,51.238 53.863,51.65 50.594,52.498 C 45.411,53.842999999999996 40.222,55.168 35.004000000000005,56.379 C 33.981,56.616 33.031000000000006,57.134 32.120000000000005,57.68" 43 | }, 44 | { 45 | "path": "C 92.903,116.328 90.418,116.521 88.036,117.062 C 81.809,118.478 75.557,119.786 69.31700000000001,121.148 C 68.956,121.22699999999999 68.634,121.475 68.24000000000001,121.39999999999999" 46 | }, 47 | { 48 | "path": "C 81.033,94.113 78.43599999999999,94.559 75.917,95.23 C 70.44200000000001,96.687 64.955,98.104 59.481,99.565 C 58.628,99.79299999999999 57.858000000000004,100.231 57.08,100.64" 49 | }, 50 | { 51 | "path": "C 40.644999999999996,79.979 38.031,80.238 35.589999999999996,80.926 C 30.883999999999997,82.254 26.147999999999996,83.477 21.439999999999998,84.802 C 20.650999999999996,85.024 19.849999999999998,85.06200000000001 19.038999999999998,85.039" 52 | }, 53 | { 54 | "path": "C 149.41400000000002,103.49300000000001 146.832,104.304 144.202,104.851 C 139.793,105.768 135.399,106.755 131.0,107.72 C 130.057,107.92699999999999 129.195,108.33 128.36,108.8" 55 | }, 56 | { 57 | "path": "C 116.92699999999999,17.823999999999998 117.374,19.017 118.122,20.262999999999998 C 120.189,23.701999999999998 122.143,27.209999999999997 124.152,30.685 C 124.622,31.499 125.043,32.352 125.144,33.318 C 125.62400000000001,33.594 126.19900000000001,33.714999999999996 126.724,34.065999999999995 C 127.22800000000001,36.8 129.01,38.956999999999994 130.293,41.352999999999994 C 132.01000000000002,44.559 133.969,47.62899999999999 135.691,50.833999999999996 C 136.04500000000002,51.492999999999995 136.189,52.221 136.486,52.846999999999994 C 136.904,53.324999999999996 137.589,53.25299999999999 138.023,53.803999999999995 C 138.409,56.129999999999995 139.936,58.01199999999999 141.083,60.07899999999999 C 143.472,64.38799999999999 146.005,68.615 148.428,72.905 C 148.892,73.726 149.114,74.57300000000001 149.35999999999999,75.441" 58 | }, 59 | { 60 | "path": "C 44.712999999999994,81.024 45.958,82.54400000000001 46.894999999999996,84.191 C 49.224999999999994,88.288 51.602999999999994,92.358 53.974,96.431 C 54.628,97.55499999999999 55.223,98.69 55.57899999999999,99.854 C 56.023999999999994,100.363 56.708999999999996,100.292 57.157,100.859 C 57.44199999999999,103.08099999999999 58.934,104.874 59.986,106.866 C 60.418,107.684 60.866,108.517 61.413,109.27 C 61.748,109.72999999999999 61.775999999999996,110.205 61.76,110.72" 61 | }, 62 | { 63 | "path": "C 14.265,28.037000000000003 16.159,30.978 17.865,34.026 C 18.41,34.999 18.851,35.982000000000006 19.198999999999998,37.050000000000004 C 19.522,37.196000000000005 19.889999999999997,37.339000000000006 20.214999999999996,37.43000000000001 C 21.564999999999998,40.99600000000001 23.744999999999997,44.00800000000001 25.531999999999996,47.233000000000004 C 26.894999999999996,49.693000000000005 28.297999999999995,52.133 29.735999999999997,54.550000000000004 C 30.188999999999997,55.312000000000005 30.33,56.142 30.560999999999996,56.959" 64 | }, 65 | { 66 | "path": "C 166.363,71.118 164.25400000000002,72.029 162.082,72.568 C 159.351,73.245 156.647,74.035 153.912,74.685 C 152.731,74.96600000000001 151.745,75.56400000000001 150.68,76.04" 67 | }, 68 | { 69 | "path": "C 73.30199999999999,3.584 73.84599999999999,4.941 74.574,6.334 C 76.521,10.059 78.692,13.674 80.24,17.6" 70 | }, 71 | { 72 | "path": "C 150.32299999999998,49.480000000000004 149.14,50.064 147.927,50.388 C 145.481,51.041 143.03199999999998,51.693999999999996 140.599,52.397 C 139.65699999999998,52.669 138.816,53.147999999999996 137.95999999999998,53.601" 73 | }, 74 | { 75 | "path": "C 138.336,30.222 136.171,31.255 133.886,31.674 C 132.597,31.91 131.332,32.326 130.042,32.611 C 128.875,32.869 127.77,33.312999999999995 126.8,34.04" 76 | }, 77 | { 78 | "path": "C 15.299,39.037 11.209999999999999,39.91 7.282,41.245999999999995 C 6.721,41.437 6.159,41.312 5.6,41.35999999999999" 79 | } 80 | ] -------------------------------------------------------------------------------- /Test/occlusion1_sol_rec.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Test/occlusion1_rec.svg: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------------------------------------------------------