我正在寻找python解决方案。
我正在使用opencv来检测图像中的框,但是我感觉结果不一致。盒子应该始终是二维的,但有时可能会有点歪斜或白色。
我只能检测盒子区域。
我尝试过:
import cv2
# reading image
img = cv2.imread('cardboard.jpg')
# thresholding the image
ret,thresh = cv2.threshold(img, 127, 229, cv2.THRESH_TOZERO_INV)
edged = cv2.cvtColor(thresh, cv2.COLOR_BGR2GRAY)
# collectiong contours
_, contours,h = cv2.findContours(edged, cv2.RETR_TREE,
cv2.CHAIN_APPROX_SIMPLE)
# looping through contours
for cnt in contours:
x, y, w, h = cv2.boundingRect(cnt)
if w > 100 and h > 100:
approx = cv2.approxPolyDP(cnt,0.01*cv2.arcLength(cnt,True),True)
if len(approx) < 6:
cv2.drawContours(img_x,[cnt],0,(0,215,255),3)
cv2.imwrite('contours/img.jpg', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
答案 0 :(得分:2)
我尝试了您的代码,这种方法仅适用于第二张图像(在9个框中标识8个),因为您的框带有白色标签,并且与背景形成了很好的对比。但是,它不适用于上传的第一张图片。
在第二张图片中,由于光照变化,您的代码无法识别所有盒子(这会导致阈值问题,因此仅检测到8个盒子),所以我建议您阅读一下计算机视觉照明,因为它可以简化您的操作编码很多。话虽如此,我已经对您的代码进行了更改,也许可以让您了解如何进行操作(代码中有注释)...我已经用第二张图片对其进行了测试,它确实可以识别所有方框,但是仍然应该经过进一步测试。如果要在张贴的两种图像上都检测到框,则需要使用其他方法。
代码:
import cv2
# reading image
img = cv2.imread('boxes.jpg')
# thresholding the image
ret,thresh = cv2.threshold(img, 127, 229, cv2.THRESH_TOZERO)
edged = cv2.cvtColor(thresh, cv2.COLOR_BGR2GRAY)
# ADDED BINARY THRESHOLD
ret,thresh = cv2.threshold(edged,100,255,cv2.THRESH_BINARY)
# collectiong contours
_, contours,h = cv2.findContours(edged, cv2.RETR_TREE,
cv2.CHAIN_APPROX_SIMPLE)
cv2.imshow('img', thresh)
# looping through contours
for cnt in contours:
x, y, w, h = cv2.boundingRect(cnt)
if w > 50 and h > 50:
#ADDED SIZE CRITERION TO REMOVE NOISES
size = cv2.contourArea(cnt)
if size > 500:
#CHANGED DRAWING CONTOURS WITH RECTANGLE
cv2.rectangle(img,(x,y),(x+w,y+h),(0,215,255),2)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果:
编辑:
我为第二张图像制作了代码示例,这可能在进一步尝试中很有用。首先,为图像设定阈值,达到上限并绘制轮廓。
然后将图像转换为HSV色彩空间,并使用cv2.inRange()
查找颜色。
然后通过搜索轮廓并在其上绘制来填充它。
最后在轮廓上绘制矩形。
import cv2
import numpy as np
# reading image
img = cv2.imread('boxes.jpg')
img_x = img.copy()
for low_thresh in range(0,25):
ret,thresh = cv2.threshold(img, low_thresh*10, 255, cv2.THRESH_TOZERO_INV)
edged = cv2.cvtColor(thresh, cv2.COLOR_BGR2GRAY)
_, contours,h = cv2.findContours(edged, cv2.RETR_TREE,
cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
size = cv2.contourArea(cnt)
if 500 < size < 50000:
x, y, w, h = cv2.boundingRect(cnt)
if w > 100 and h > 100:
approx = cv2.approxPolyDP(cnt,0.01*cv2.arcLength(cnt,True),True)
if len(approx) < 6:
cv2.drawContours(img,[cnt],0,(0,215,255),3)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower_yellow = np.array([25,50,50])
upper_yellow = np.array([50,255,255])
mask_yellow = cv2.inRange(hsv, lower_yellow, upper_yellow)
res_yellow = cv2.bitwise_and(img,img, mask=mask_yellow)
gray_yellow = cv2.cvtColor(res_yellow, cv2.COLOR_BGR2GRAY)
_,thresh_yellow = cv2.threshold(mask_yellow,10,255,cv2.THRESH_BINARY)
_, contours_yellow, hierarhy = cv2.findContours(thresh_yellow,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
for c in contours_yellow:
size = cv2.contourArea(c)
if size > 500:
cv2.drawContours(thresh_yellow, [c], -1, 255, -1)
_, contours_yellow, hierarhy3 = cv2.findContours(thresh_yellow,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
for c in contours_yellow:
size = cv2.contourArea(c)
if size > 500:
cv2.drawContours(thresh_yellow, [c], -1, 255, -1)
x, y, w, h = cv2.boundingRect(c)
cv2.rectangle(img_x,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow('img', img_x)
cv2.waitKey(0)
cv2.destroyAllWindows()
希望它会有所帮助。干杯!