簡體   English   中英

如何僅獲取輪廓區域顏色范圍

[英]how to get only contour area color range

我想獲得輪廓區域顏色范圍並做一些條件,例如這是輸入圖像:輸入圖像 下面是查找輪廓的代碼:

import cv2

img = cv2.imread('D:/original.png', cv2.IMREAD_UNCHANGED)

#convert img to grey
img_grey = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#set a thresh
thresh = 100
#get threshold image
ret,thresh_img = cv2.threshold(img_grey, thresh, 255, cv2.THRESH_BINARY)
#find contours
contours, hierarchy = cv2.findContours(thresh_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

現在我正在嘗試獲取每個輪廓顏色並編寫條件,例如:

如果 contours[0] 在顏色范圍 ((100,100,100),(200,200,200)) 中,則 drawContour

我要做的所有事情是:獲取每個輪廓區域並檢查所選輪廓是否在特定顏色范圍內。

為了提取按顏色區分的單個輪廓,解決此問題的邏輯方法是使用不同的 colors 而不是將圖像轉換為grayscale

您可以在單個頻道上工作。 例如,對於blue通道:

thresh = 100

ret,thresh_img = cv2.threshold(b, thresh, 255, cv2.THRESH_BINARY)

在藍色通道上脫粒

然后結合按bit_wise操作,您可以提取特定的輪廓。

另一種方法是用Canny運算符替換threshold運算符。

thresh1 = 40
thresh2 = 120
#get canny image
thresh_img = cv2.Canny(img[:,:,0], thresh1,thresh2)
#find contours
contours, hierarchy = cv2.findContours(thresh_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

產生以下輪廓: 精明的藍色頻道

OpenCV 文檔建議使用Canny作為輪廓的預處理。

我們可以從cv2.kmeans開始執行顏色聚類 - 類似於以下教程中描述的內容。

結果是標簽列表。
每個 label(標簽 0、label 1,...)代表屬於特定顏色簇的所有像素。

將 K-Means 應用於 colors 聚類的示例:

# Reshape the image into a 2D array with one row per pixel and three columns for the color channels.
data = image.reshape((cols * rows, 3))

# Perform K-Means clustering on the image.
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
_, labels, centroids = cv2.kmeans(data, K, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)

迭代標簽,並創建一個包含255的掩碼,其中labels == k

mask = np.zeros((rows*cols, 1), np.uint8)  # Create a zerod mask in the size of image.
mask[labels == k] = 255  # Place 255 where labels == k (all labels equals 0 are going to be 255 then all labels equals 1...)
mask = mask.reshape((rows, cols))  # Reshape the mask back to the size of the image.

對於每個面具應用以下階段:

  • 查找輪廓。
  • 對於每個輪廓,找到輪廓區域,並忽略相對較小的輪廓。
  • 獲取輪廓中的第一個坐標: x, y = tuple(c[0][0])
  • 獲取該坐標中像素的顏色: color = original_image[y, x]
  • 使用該顏色繪制輪廓(主要用於測試): cv2.drawContours(colored_mask, [c], 0, color.tolist(), -1)

完整的代碼示例:

import cv2
import numpy as np

K = 16  # Number of color clusters (16 is a bit larger than the accrual number of colors).

# Load the image and convert it float32 (kmeans requires float32 type).
original_image = cv2.imread('original.png')
image = original_image.astype(np.float32)

cols, rows = image.shape[1], image.shape[0]

# Reshape the image into a 2D array with one row per pixel and three columns for the color channels.
data = image.reshape((cols * rows, 3))

# Perform K-Means clustering on the image.
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
_, labels, centroids = cv2.kmeans(data, K, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)

# Convert the labels back into an image (for testing).
quantized_image = centroids[labels].reshape(image.shape).astype(np.uint8)

# Save the quantized_image image (for testing).
cv2.imwrite('quantized_image.png', quantized_image)

for k in range(K):
    mask = np.zeros((rows*cols, 1), np.uint8)  # Create a zeroed mask in the size of image.
    mask[labels == k] = 255  # Place 255 where labels == k (all labels equals 0 are going to be 255 then all labels equals 1...)
    mask = mask.reshape((rows, cols))  # Reshape the mask back to the size of the image.
    #cv2.imshow(f'mask {k}', mask)  # Show mask for testing

    cnts = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]  # Find contours
    for c in cnts:
        area_tresh = 500
        area = cv2.contourArea(c)
        if area > area_tresh:  # Ignore relatively small contours
            colored_mask = np.zeros_like(original_image)  # Initialize colored_mask with zeros
            x, y = tuple(c[0][0])  # First coordinate in the contour
            color = original_image[y, x]  # Get the color of the pixel in that coordinate
            cv2.drawContours(colored_mask, [c], 0, color.tolist(), -1)  # Draw contour with the specific color
            cv2.imshow(f'colored_mask {k}', colored_mask)  # Show colored_mask for testing
            cv2.imwrite(f'colored_mask_{k}.png', colored_mask)  # Save as PNG for testing
            continue  # Assume only the first large contour is relevant - continue to next iteration

cv2.waitKey()
cv2.destroyAllWindows()

很少有 output 個樣本:

在此處輸入圖像描述

在此處輸入圖像描述

在此處輸入圖像描述

在此處輸入圖像描述

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM