在下面的灰度图像中,我试图识别我手动标记为红色的对象。有没有人建议如何做到这一点?
我试图使用高斯模糊和阈值处理,但不能专门识别这些粒子。边缘检测是一种好方法吗?欢迎任何建议。
答案 0 :(得分:3)
您的图片看起来像是机器学习的合适目标。
您应该能够通过简单的阈值处理以及可能的后续大小过滤来获取对象。
修改强>:
这就是我使用Trainable Weka分割的方式:
答案 1 :(得分:1)
我只是从命令行使用ImageMagick快速进行此操作。我相信通过查看检测到的斑点的squareness
可以改善它,但我没有无限的时间可用,你说任何想法都是受欢迎的......
首先,我对图像进行了阈值处理,然后我将每个像素替换为水平行中的最大像素,左右为6个像素 - 这是将每个咖啡豆形状的两半连接在一起。命令是这样的:
convert http://i.stack.imgur.com/mr0OM.jpg -threshold 80% -statistic maximum 13x1 w.jpg
它看起来像这样:
然后我在其上添加 Connected Components Analysis 以找到blob,如下所示:
convert http://i.stack.imgur.com/mr0OM.jpg \
-threshold 80% -statistic maximum 13x1 \
-define connected-components:verbose=true \
-define connected-components:area-threshold=500 \
-connected-components 8 -auto-level output.png
Objects (id: bounding-box centroid area mean-color):
0: 1280x1024+0+0 642.2,509.7 1270483 srgb(4,4,4)
151: 30x303+137+712 152.0,863.7 5669 srgb(255,255,255)
185: 29x124+410+852 421.2,913.2 2281 srgb(255,255,255)
43: 48x48+445+247 467.9,271.5 1742 srgb(255,255,255)
35: 21x94+234+214 243.7,259.2 1605 srgb(255,255,255)
10: 52x49+183+31 209.9,56.2 1601 srgb(255,255,255)
30: 31x86+504+176 523.1,217.2 1454 srgb(255,255,255)
171: 61x39+820+805 856.0,825.7 1294 srgb(255,255,255)
119: 20x78+1212+625 1221.6,664.3 1277 srgb(255,255,255)
17: 44x40+587+106 608.3,124.9 1267 srgb(255,255,255)
94: 19x70+1077+545 1086.1,580.6 1100 srgb(255,255,255)
59: 43x33+947+329 967.4,344.3 1092 srgb(255,255,255)
40: 39x32+735+235 754.4,251.0 1074 srgb(255,255,255)
91: 22x62+1258+540 1268.3,571.0 1045 srgb(255,255,255)
18: 23x50+197+124 207.1,148.1 996 srgb(255,255,255)
28: 40x28+956+165 976.8,177.7 970 srgb(255,255,255)
76: 22x55+865+467 875.6,493.8 955 srgb(255,255,255)
187: 18x59+236+858 244.4,886.4 928 srgb(255,255,255)
211: 46x27+720+997 743.8,1009.0 891 srgb(255,255,255)
206: 19x47+418+977 427.5,1000.5 804 srgb(255,255,255)
57: 21x44+231+313 241.4,335.5 769 srgb(255,255,255)
97: 20x45+1215+553 1224.3,574.3 766 srgb(255,255,255)
52: 19x47+516+293 525.4,316.2 752 srgb(255,255,255)
129: 20x41+18+645 28.2,665.1 746 srgb(255,255,255)
83: 21x45+1079+497 1088.1,518.9 746 srgb(255,255,255)
84: 17x44+636+514 644.0,535.7 704 srgb(255,255,255)
62: 19x43+514+348 523.3,369.3 704 srgb(255,255,255)
201: 19x42+233+951 242.3,971.8 675 srgb(255,255,255)
134: 21x39+875+659 884.3,676.9 667 srgb(255,255,255)
194: 25x32+498+910 509.5,924.6 625 srgb(255,255,255)
78: 19x38+459+483 467.8,501.8 622 srgb(255,255,255)
100: 20x37+21+572 30.6,589.4 615 srgb(255,255,255)
53: 18x37+702+296 710.5,314.5 588 srgb(255,255,255)
154: 18x37+1182+723 1191.2,741.3 566 srgb(255,255,255)
181: 47x18+808+842 827.6,850.4 565 srgb(255,255,255)
80: 19x33+525+486 534.2,501.9 544 srgb(255,255,255)
85: 17x34+611+517 618.9,533.4 527 srgb(255,255,255)
203: 21x31+51+960 60.5,974.6 508 srgb(255,255,255)
177: 19x30+692+827 700.7,841.5 503 srgb(255,255,255)
它显示了它找到的所有斑点,它们的边界和质心。然后我让ImageMagick将检测到的框绘制到您的图像上,如下所示:
只是为了解释输出,每一行代表一个blob。让我们看看第二行,即:
151: 30x303+137+712 152.0,863.7 5669 srgb(255,255,255)
这意味着blob是30像素宽,303像素高,它位于距图像左侧137像素和距离顶部712像素的位置。所以它基本上是图像左下角最高的绿色框。 152,863是其质心的x,y坐标,其面积为5669像素,颜色为白色。
正如我所说,它可以通过查看斑点两侧的比例来找到方形来改进,但它可能会给你一些想法。顺便问一下,你能说出blob是什么吗?
答案 2 :(得分:1)
我给了以下alg。在评论OP的问题时,这是一个简短的片段,所以为什么不给出带有python的opencv的书面答案。
希望这比Mark Setchell的答案更具有可扩展性,而且与OP的标签有关。
import cv2
import numpy as np
img = cv2.imread("a.jpg", cv2.IMREAD_GRAYSCALE)
ret,thresh = cv2.threshold(img,127,255,0)
contours,hierarchy = cv2.findContours(thresh, 1, 2)
#color image for testing purposes
color = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)
for cnt in contours:
x,y,w,h = cv2.boundingRect(cnt)
if w>h: delta = w/h
else: delta = h/w
if delta<4 and w>10 and h>10:
cv2.rectangle(color,(x,y),(x+w,y+h),(0,0,255),2)
cv2.imwrite("c.jpg", color)
它提供了6-7个额外的小对象,这些对象是错误的检测。但是,如我所提到的那样,使用erode
和dilate
函数以及为treshold
边缘检测算法切换canny
可以很容易地改善这种情况。可以通过要求更长的矩形宽度和长度来整理错误检测。
更新了代码
只是为了展示一些你可以玩的额外选项。
import cv2
import numpy as np
img = cv2.imread("a.jpg", cv2.IMREAD_GRAYSCALE)
img[np.where(img<100)] = 0 #set all pixels with intensities bellow 100 to 0
img[(img>100) & (img<244)] += 10 #same as above, set all other pixels>100 and smaller than 254 (when you add 10) to be more "white" than before, exaggerating objects
img = cv2.equalizeHist(img) #just for good measure I suppose?
#matrices filled with '1' everywhere, different dimensions
erode_kernel = np.ones((4,4))
dilate_kernel = np.ones((9,9))
small_dilate_kernel = np.ones((2,2))
erode = cv2.erode(img, erode_kernel)
dilate = cv2.dilate(erode, dilate_kernel)
canny = cv2.Canny(dilate, 180, 255) #if pixel value is not in range 180-255 it is not considered for edge detection
canny = cv2.dilate(canny, small_dilate_kernel) #just to combine close edges to make them appear as a single edge, might be a bad idea
contours,hierarchy = cv2.findContours(canny, cv2.RETR_EXTERNAL, #retr_exernal ignores all inside-object features and returns just the outside-most contours
cv2.CHAIN_APPROX_NONE)
a = np.zeros(img.shape) #test image to see what happened so far
cv2.drawContours(a, contours, -1, (255,255,255), 1)
cv2.imwrite("contours.jpg", a)
#color image for testing purposes
color = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)
for cnt in contours:
x,y,w,h = cv2.boundingRect(cnt)
if w>h: delta = w/h
else: delta = h/w
if delta<4 and w>20 and h>20:
cv2.rectangle(color,(x,y),(x+w,y+h),(0,0,255),2)
cv2.imwrite("c.jpg", color)
祝你好运,comp。愿景需要花费大量时间才能让它以你想要的方式运作。花点时间阅读手册。由于我们现在正在努力将它们组合在一起作为单个对象,所以重叠的东西很难设置。
如果您可以将咖啡豆显示为圆圈,则可以尝试使用HoughCircle
检测。但看到他们是如何相当不规则,我不太确定这是最好的方式。训练你自己的haar级联可能是你最好的选择,但我从来没有这样做过,所以我在这方面帮不了多少。
答案 3 :(得分:1)
感谢所有建议。我已经研究了很多解决这个问题的方法,我得到的最好的结果就是使用opencv和haar一样的功能级联分类。
我遵循了本教程,并且达到了很高的准确度:
http://coding-robin.de/2013/07/22/train-your-own-opencv-haar-classifier.html
以下是前两张图片的结果,对分类器进行了一些优化,可以进一步改进: