## Task Description Read an image in grayscale mode, use Sobel operators to detect and output the edge components, and design a self-portrait pattern with sketch-like lines. ## Operating Environment - MacOS Monterey 12.2 - PyCharm 2019.3.3 - Python 3.8 - OpenCV 4.5.5 ## Implementation Features and Methods 1. Reduce Noise and Smooth the Image - Use `cv2.GaussianBlur('image name', Filter_Size, 0)` with Gaussian filter function to filter the image (smooth, filter, and denoise); `Filter_Size` is 3x3. 2. Edge Detection - Use the Sobel operator to calculate edge pixels in both horizontal and vertical directions. The calculation involves the surrounding eight pixels within a 3x3 neighborhood. - Vertical method: Multiply each pixel in the 3x3 neighborhood by the corresponding vertical Sobel mask, sum the results, and obtain the vertical gradient Gx for edge detection. - Horizontal method: Multiply each pixel in the 3x3 neighborhood by the corresponding horizontal Sobel mask, sum the results, and obtain the horizontal gradient Gy for edge detection. - Use `cv2.Sobel('image name', image depth, dx, dy, Filter_Size)` to calculate the gradient magnitudes in the X (vertical) and Y (horizontal) directions. 3. Combine Feature Maps - Use `cv2.addWeighted()` to merge the calculated results of X and Y direction gradients, obtaining the output edge component map. 4. Color Inversion - Perform color inversion on the points obtained from edge detection. Read each pixel value P, then write 255-P into a new empty array to get the color-inverted image. 5. Image Binarization - Set `cv2.threshold('image name', Thresh_Value, Maxval_Value, method)` to make the lines clearly visible, achieving a sketch-like effect. 6. Canny Edge Detection - Use `cv2.Canny('image name', minVal, maxVal)`. The Canny algorithm is a composite edge detection algorithm that combines Gaussian filter, gradient detection, non-maximum suppression, and edge tracking by hysteresis. ## Execution Results Original Image ![Picture1](https://hackmd.io/_uploads/SkdHTw5YT.png) Sobel_X ![Picture2](https://hackmd.io/_uploads/HkpH6w5Ya.png) Sobel_Y ![Picture3](https://hackmd.io/_uploads/BkrUavcK6.png) Sobel_XY (Merged using `addWeighted()`) ![Picture4](https://hackmd.io/_uploads/rJn86D5Y6.png) Sobel_XY (Using `cv2.Sobel()` function) ![Picture5](https://hackmd.io/_uploads/Bk4wTPcKa.png) Color Inversion ![Picture6](https://hackmd.io/_uploads/rkqPTPqt6.png) Image Binarization (Using Binary Type) ![Picture7](https://hackmd.io/_uploads/rkGdpD9Y6.png) Image Binarization (Using Tozero Type) ![Picture8](https://hackmd.io/_uploads/SyF_6P5Y6.png) Canny Edge Detection ![Picture9](https://hackmd.io/_uploads/ByWF6v9F6.png) Canny Edge Detection + Color Inversion ![Picture10](https://hackmd.io/_uploads/HkYFTvctp.png) ``` import cv2 import numpy as np # Read the original image img = cv2.imread('fig.jpg') # Display original image cv2.imshow('Original', img) cv2.waitKey(0) # Convert to graycsale img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Blur the image for better edge detection img_blur = cv2.GaussianBlur(img_gray, (3,3), 0) # Sobel Edge Detection sobelx = cv2.Sobel(src=img_blur, ddepth=cv2.CV_64F, dx=1, dy=0, ksize=3) # Sobel Edge Detection on the X axis sobely = cv2.Sobel(src=img_blur, ddepth=cv2.CV_64F, dx=0, dy=1, ksize=3) # Sobel Edge Detection on the Y axis sobelxy = cv2.Sobel(src=img_blur, ddepth=cv2.CV_64F, dx=1, dy=1, ksize=3) # Combined X and Y Sobel Edge Detection sobelx=cv2.convertScaleAbs(sobelx) sobely=cv2.convertScaleAbs(sobely) sobelxy=cv2.convertScaleAbs(sobelxy) dst = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0) # Display Sobel Edge Detection Images cv2.imshow('Sobel X', sobelx) cv2.waitKey(0) cv2.imwrite('Sobel_X.jpg', sobelx) cv2.imshow('Sobel Y', sobely) cv2.waitKey(0) cv2.imwrite('Sobel_Y.jpg', sobely) cv2.imshow('Sobel X Y using Sobel() function', sobelxy) cv2.waitKey(0) cv2.imwrite('Sobel_XY.jpg', sobelxy) cv2.imshow('Sobel X Y using addWeighted function', dst) cv2.waitKey(0) cv2.imwrite('Sobel_XY_dst.jpg',dst) # Canny Edge Detection edges = cv2.Canny(image=img_blur, threshold1=100, threshold2=200) # Canny Edge Detection # Display Canny Edge Detection Image cv2.imshow('Canny Edge Detection', edges) cv2.waitKey(0) cv2.imwrite('Canny_edge.jpg', edges) ret, th = cv2.threshold(edges, 127, 255, cv2.THRESH_BINARY_INV) height,width=dst.shape img=np.zeros((height,width,1),np.uint8) for i in range(height): for j in range(width): img[i,j]=255-dst[i,j] cv2.imshow('transform', img) cv2.waitKey(0) cv2.imwrite('transform.jpg', img) img = cv2.GaussianBlur(img, (3,3), 0) dst = cv2.GaussianBlur(dst, (3,3), 0) ret, th1 = cv2.threshold(img, 200, 255, cv2.THRESH_BINARY) ret, th2 = cv2.threshold(dst, 60, 255, cv2.THRESH_BINARY_INV) ret, th3 = cv2.threshold(img, 200, 255, cv2.THRESH_TRUNC) ret, th4 = cv2.threshold(img, 200, 255, cv2.THRESH_TOZERO) ret, th5 = cv2.threshold(img, 200, 255, cv2.THRESH_TOZERO_INV) titles = ['Canny', 'BINARY','TOZERO'] images = [th, th1, th4] for i in range(3): cv2.imshow(titles[i],images[i]) cv2.waitKey(0) cv2.imwrite(titles[i]+'.jpg', images[i]) cv2.destroyAllWindows() ```