OpenCV (Python) - chanandrew96/MyLearning GitHub Wiki

Knowledge about image & color

RGB / HSV / HSL

RGB:

  • RGB使用RGB三種顏色顯示,亮度改變的時候三種顏色都會同時改變,人眼對這種顏色改變的敏感程度較低,常用於系統顯示,較少用於圖像處理
    HSV:
  • HSV基於三種元素: Hue(色調)、Saturation(飽和度)、Value,由於整體的色彩改變敏感度較高,比較多用於圖像識別
    HLS:
  • HLS基於三種元素: Hue(色調)、Saturation(飽和度)、Lightness(亮度),
  • 由於HLS中白色由亮度決定,而HSV中的白色由Saturation和Value共同決定,所以在檢測白色的時候使用HLS會更準確

Contours

For finding contours on image, we need to remove the noise as possible. Below are some common way to pre-process the image

Pre-processing Steps

  1. Read your image
  2. To GrayScale
  3. Image Blurring (Image Smoothing)
  4. CLAHE (Contrast Limited Adaptive Histogram Equalization)
  5. Threshold
  6. Find Contours
  7. Find Contours Area
  8. Draw contour

Read your image

Before processing with the image, you will need to read the image using OpenCV

img = cv2.imread(img_path, cv2.IMREAD_UNCHANGED)

We use cv2.IMREAD_UNCHANGED here to keep data same as source file, or you may use/ignore the parameter here
You may use cv2.IMREAD_GRAYSCALE to perform the grayscale conversion, but quote from OpenCV Notes, the result may be difference from using the cvtColor function

When using IMREAD_GRAYSCALE, the codec's internal grayscale conversion will be used, if available. Results may differ to the output of cvtColor()

To GrayScale

Since most functions expected with grayscale image, we need to convert the image into grayscale at the first step.

img_grey = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

Image Blurring (Image Smoothing)

Next step, we remove noise and decrease the acutance & sharpness to prevent unnecessary information
Smoothing Images tutorial from OpenCV
圖像上的每一個像素點都會根據Kernel的大小重新計算出新的像素值,如果Kernel的大小為3x3,則會以包圍像素點的共8個像素點計算 (Reference)
image

Gaussian Blur (高斯平滑)

Calling cv.GaussianBlur
Kernel size must be odd
使用高斯分佈曲線,透過SigmaX和SigmaY計算X和Y方向的標準差,以及borderType處理邊界的方式來決定像素點的新像素值
當ksize和sigma的數值愈大的時候,新的圖像便會愈為模糊

Highly effective in removing Gaussian noise from an image

blur = cv.GaussianBlur(img,(5,5),0)

Median Blurring (中值平滑)

Calling cv.medianBlur
滑動窗口/Kernel size must be odd
Median Blurring會排序滑動窗口的像素點,然後取其中間值作為新的像素值

Highly effective against salt-and-pepper noise in an image

median = cv.medianBlur(img,5)

Bilateral Filtering (雙邊濾波器/雙邊平滑)

Bilateral Filtering可以做到去噪保邊,當中心點周圍的像素點值的差異非常大的時候,這個像素值便不會對中心點有影響,以做到保邊
d為滑動窗口的大小,當數值大於5的時候處理速度比較慢,要處理嚴重Noise的時候可以使用d>=9
當SigmaColor(亮度差異)和SigmaSpace(空間距離)<10的時候,Blur的效果不會太明顯
Calling cv.bilateralFilter

The Gaussian function of space makes sure that only nearby pixels are considered for blurring, while the Gaussian function of intensity difference makes sure that only those pixels with similar intensities to the central pixel are considered for blurring
Preserves the edges since pixels at edges will have large intensity variation

blur = cv.bilateralFilter(img,9,75,75)

CLAHE

Contrast Limited Adaptive Histogram Equalization (CLAHE) used to equalize image
可能圖片的顏色偏暗/光,在直方圖(Histogram)中偏左(暗)/右(光),使用CLAHE便可以將色彩平均分布到整個直方圖中
tileGridSize是圖像上的Tites,即圖像上的每一個小塊
clipLimit定義了直方圖上的最高特定值,CLAHE會將在直方圖上超過特定值的重新均衡地分布到直方圖以生成新的直方圖

clahe = cv2.createCLAHE(clipLimit, (tileGridSize_X, tileGridSize_Y))
clahe_img = clahe.apply(img)

CLAHE Reference

[OpenCV] 淺談直方圖均衡化Histogram Equalization、AHE均衡、CLAHE均衡
OpenCV-Python自适应直方图均衡类CLAHE及方法详解

Threshold

Threshold(二值化)將圖像上的灰階值介定高於或低於Thresh的分別兩種像素點,然後根據選擇的類型作不同的處理,包括白色化、填色、保持原色
由於使用灰階值去處理,輸入的圖像需要是灰階影像

ret,thresh_img = cv2.threshold(img, thresh, maxval, cv2.THRESH_BINARY)

Threshold Reference

opencv: 阈值处理(cv2.threshold) 探究(图示+源码)

Find Contours

Calling cv2.findContours
Select difference mode and method
Mode:

  • cv2.RETR_TREE: With parent-child relationship
  • cv2.RETR_LIST: More effective, without parent-child relationship
  • cv2.RETR_EXTERNAL: Only return the outest contour 只返回最外層的輪廓
  • cv2.RETR_CCOMP: Divided all layer into 2 layer (Internal & External) Method:
  • cv2.CHAIN_APPROX_NONE: Save all contours point on edge
  • cv2.CHAIN_APPROX_SIMPLE: Save contours corner point only
  • cv2.CHAIN_APPROX_TC89_L1: Similar to Teh-Chini chain
  • cv2.CHAIN_APPROX_TC89_KCOS: Similar to Teh-Chini chain
contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

Find Contours Reference

findContours函数参数详解
Contours: Getting Stated

Find Contours Area

Call cv2.contourArea() for the contour area

cnt = contours[0]
area = cv2.contourArea(cnt)

In case you want the contour with largest area, you could sort the contours list by contourArea first

cnts_Sorted = sorted(contours, key=cv2.contourArea, reverse=True)   

Or, you can directly get the contour with max contour area

c = max(contours, key = cv2.contourArea)
x,y,w,h = cv2.boundingRect(c)

You could calculate and compare the area with the input image area

# Get the total area of input image in pixels
total_pixels = img.shape[0] * img.shape[1]
# Get the contour area ratio
contour_ratio = contour_area / float(total_pixels) * 100
# Get the non-contour area ratio
non_contour_ratio = 100 - contour_ratio

Draw contour

Most of the time, you may like to check the contour return in image, you can draw the contour using cv2 also

# Create a empty image for drawing contours (using same shape as the input image)  
img_contours = np.zeros(img.shape)
# Create a empty image for drawing contours (Custom the shape of the image)
img_contours = np.zeros((height, width, channels), dtype = "uint8")
cv2.drawContours(img_contours, contours, -1, (0,255,0), 3)

Get contour arc length

Call cv2.arcLength()

perimeter = cv2.arcLength(cnt, True)

Get contour with less points

Use Douglas-Peucker algorithm to return contour with less points to form

approx = cv2.approxPolyDP(cnt, epsilon, True)

Post-processing & other operation for image in Python using OpenCV

Crop Image

img = cv2.imread("YOUR_IMG.png")
crop_img = img[y:y+h, x:x+w]

Shape of Image

img = cv2.imread("YOUR_IMG.png")
# If the image is not GrayScale/having multi-channels
height, width, channels = img.shape
# Else
height, width= img.shape

Features Detection

We can detect the features on image using cv2.goodFeaturesToTrack() in pixel level, or using cv2.cornerSubPix() in subpixel level

OpenCV Python Reference