我正在尝试使用阈值来分割颜色。但这并不是行不通。我如何分割这张图片中的红色和绿色。
感谢
使用 Kmeans 之后的图像
使用阈值分割后的该图像
我的代码
import numpy as np
import cv2
img = cv2.imread('watermelon.jpg')
Z = img.reshape((-1,3))
# convert to np.float32
Z = np.float32(Z)
# define criteria, number of clusters(K) and apply kmeans()
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K = 4
ret,label,center=cv2.kmeans(Z,K, criteria,10,cv2.KMEANS_RANDOM_CENTERS)
# Now convert back into uint8, and make original image
center = np.uint8(center)
res = center[label.flatten()]
res2 = res.reshape((img.shape))
gray = cv2.cvtColor(res2,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
#segmentation
gray = cv2.cvtColor(res2,cv2.COLOR_BGR2GRAY)
ret, threshseg = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
cv2.imwrite('img_CV2_95.jpg',threshseg)
cv2.imwrite('img_CV2_94.jpg',res2)
cv2.imshow('threshseg',threshseg)
cv2.imshow('thresh',thresh)
cv2.imshow('res2',res2)
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Run Code Online (Sandbox Code Playgroud)
我会利用标签数组的优势并将其用于分段。
首先将其整形回与输入图像相同的宽度/高度。
labels = labels.reshape((img.shape[:-1]))
Run Code Online (Sandbox Code Playgroud)
现在,假设您想要抓取带有 label 的所有像素2。
mask = cv2.inRange(labels, 2, 2)
Run Code Online (Sandbox Code Playgroud)
只需使用它来cv2.bitwise_and遮盖图像的其余部分即可。
mask = np.dstack([mask]*3) # Make it 3 channel
ex_img = cv2.bitwise_and(img, mask)
Run Code Online (Sandbox Code Playgroud)
这种方法的好处是您不需要对任何颜色范围进行硬编码,因此相同的算法可以适用于许多不同的图像。
示例代码:
注意:针对 OpenCV 3.x 编写。OpenCV 2.4.x 的用户需要适当更改 的调用cv2.kmeans(有关差异,请参阅文档)。
import numpy as np
import cv2
img = cv2.imread('watermelon.jpg')
Z = np.float32(img.reshape((-1,3)))
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K = 4
_,labels,centers = cv2.kmeans(Z, K, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
labels = labels.reshape((img.shape[:-1]))
reduced = np.uint8(centers)[labels]
result = [np.hstack([img, reduced])]
for i, c in enumerate(centers):
mask = cv2.inRange(labels, i, i)
mask = np.dstack([mask]*3) # Make it 3 channel
ex_img = cv2.bitwise_and(img, mask)
ex_reduced = cv2.bitwise_and(reduced, mask)
result.append(np.hstack([ex_img, ex_reduced]))
cv2.imwrite('watermelon_out.jpg', np.vstack(result))
Run Code Online (Sandbox Code Playgroud)
示例输出:
不同颜色的示例输出:
如果我理解正确的话,你想分开绿色和红色吗?如果是这种情况,您可以将图像转换为 HSV 颜色空间并使用 和 提取cv2.inRange()颜色cv2.bitwise_and()。请注意,该代码是使用 OpenCV 3 和 Python 3.5 编写的。希望它能有所帮助。干杯!
示例代码:
import cv2
import numpy as np
# Read the image and transform it to HSV color space
img = cv2.imread('watermelon.jpg')
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# define ranges for colors in HSV color space you wish to display
## LIGHT AND DARK GREEN
lower_green_light = np.array([20,20,50])
upper_green_light = np.array([130,150,255])
## DARK GREEN
lower_green = np.array([0, 70, 50])
upper_green = np.array([170, 180, 100])
## RED
lower_red = np.array([170, 130, 0])
upper_red = np.array([180, 255, 255])
# Threshold with inRange() get only specific colors
mask_green = cv2.inRange(hsv, lower_green, upper_green)
mask_green_light = cv2.inRange(hsv, lower_green_light, upper_green_light)
mask_red = cv2.inRange(hsv, lower_red, upper_red)
# Perform bitwise operation with the masks and original image
res_green = cv2.bitwise_and(img,img, mask= mask_green)
res_green_light = cv2.bitwise_and(img,img, mask= mask_green_light)
res_red = cv2.bitwise_and(img,img, mask= mask_red)
# Display results
cv2.imshow('red', res_red)
cv2.imshow('green', res_green)
cv2.imshow('light green', res_green_light)
cv2.waitKey(0)
cv2.destroyAllWindows()
Run Code Online (Sandbox Code Playgroud)
结果:
| 归档时间: |
|
| 查看次数: |
9641 次 |
| 最近记录: |