## 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

Sobel_X

Sobel_Y

Sobel_XY (Merged using `addWeighted()`)

Sobel_XY (Using `cv2.Sobel()` function)

Color Inversion

Image Binarization (Using Binary Type)

Image Binarization (Using Tozero Type)

Canny Edge Detection

Canny Edge Detection + Color Inversion

```
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()
```