我想数纸箱和阅读一个特定的标签,其中将只包含3个字,白色背景在传送带使用OpenCV和Python。附件是我用来做实验的图像。到目前为止的问题是,由于噪声,我无法检测到整个框,如果我试图在x,y,w,h=cv2中检查w和h,那么它只需过滤掉文本。在这种情况下,ABC写在方框上。此外,这个盒子已经检测到顶部和底部都有尖峰,我不知道如何过滤。
下面是我正在使用的代码
import cv2
# reading image
image = cv2.imread('img002.jpg')
# convert the image to grayscale format
img_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# apply binary thresholding
ret, thresh = cv2.threshold(img_gray, 150, 255, cv2.THRESH_BINARY)
# visualize the binary image
cv2.imshow('Binary image', thresh)
# collectiong contours
contours,h = cv2.findContours(thresh, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
# looping through contours
for cnt in contours:
x, y, w, h = cv2.boundingRect(cnt)
cv2.rectangle(image,(x,y),(x+w,y+h),(0,215,255),2)
cv2.imshow('img', image)
cv2.waitKey(0)
cv2.destroyAllWindows()



此外,请建议如何裁剪文本ABC,然后应用OCR对其进行阅读。
非常感谢。
编辑2:非常感谢您的回答,根据您的建议,我修改了代码,以便它可以在视频中选中框。它工作起来就像一种魅力,希望它在很长一段时间里都无法识别出一个盒子。下面是我的代码和链接到我使用的视频。我有几个问题围绕这一点,因为我是新的OpenCV,如果你能找到一些时间来回答。
import cv2
import numpy as np
from time import time as timer
def get_region(image):
contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
c = max(contours, key = cv2.contourArea)
black = np.zeros((image.shape[0], image.shape[1]), np.uint8)
mask = cv2.drawContours(black,[c],0,255, -1)
return mask
cap = cv2.VideoCapture("Resources/box.mp4")
ret, frame = cap.read()
fps = 60
fps /= 1000
framerate = timer()
elapsed = int()
while(1):
start = timer()
ret, frame = cap.read()
# convert the image to grayscale format
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# Performing threshold on the hue channel `hsv[:,:,0]`
thresh = cv2.threshold(hsv[:,:,0],127,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)[1]
mask = get_region(thresh)
masked_img = cv2.bitwise_and(frame, frame, mask = mask)
newImg = cv2.cvtColor(masked_img, cv2.COLOR_BGR2GRAY)
# collectiong contours
c,h = cv2.findContours(newImg, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cont_sorted = sorted(c, key=cv2.contourArea, reverse=True)[:5]
x,y,w,h = cv2.boundingRect(cont_sorted[0])
cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),5)
#cv2.imshow('frame',masked_img)
cv2.imshow('Out',frame)
if cv2.waitKey(1) & 0xFF == ord('q') or ret==False :
break
diff = timer() - start
while diff < fps:
diff = timer() - start
cap.release()
cv2.destroyAllWindows()问题:
许多人再次感谢你们的时间。
发布于 2022-05-19 18:23:33
你的补充问题需要一个单独的答案:
1.如果绘制的矩形实际上在盒子的顶部而不是腰带或其他地方,我们如何100%确定?
为了这个目的,我选择了HSV颜色空间的
PRO:通道。灰色,白色和黑色的阴影(在传送带上)在这个通道是中性的。盒的棕色是对比,可以很容易地分割使用Otsu阈值。Otsu算法在没有用户input.CON的情况下找到最佳阈值,当盒子与传送带的颜色相同时,可能会遇到问题。
2.请您告诉我如何使用您在原始答案中提供的函数用于此新代码中用于视频.的其他框。
如果您希望使用边缘检测来查找框,而不使用颜色信息,则
PRO:很有可能获得许多不需要的边缘。通过使用extract_rect()函数,您可以过滤轮廓:1. have approximately 4 sides (quadrilateral)
2. are above certain areaCON如果你有超过4面的包裹/包裹/袋子,你可能需要改变这个.3。它是否正确的方式再次转换蒙面框架为灰色,找到轮廓再次绘制一个矩形。或者有更有效的方法来做到这一点。。
我觉得这是最好的方法,因为剩下的只是白色的文本区域。在我看来,应用高价值的阈值是最简单的想法。也许有一个更好的方法:)
(我不能回答第四项问题:)
发布于 2022-05-18 14:19:49
有两个步骤需要遵循:
1.框分割
我们可以假设没有背景变化,因为传送带是存在的。我们可以用不同的颜色空间分割盒子。在以下中,我使用了HSV颜色空间:
img = cv2.imread('box.jpg')
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# Performing threshold on the hue channel `hsv[:,:,0]`
th = cv2.threshold(hsv[:,:,0],127,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)[1]隐藏二值图像中最大的轮廓:
def get_region(image):
contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
c = max(contours, key = cv2.contourArea)
black = np.zeros((image.shape[0], image.shape[1]), np.uint8)
mask = cv2.drawContours(black,[c],0,255, -1)
return mask
mask = get_region(th)在原始图像上应用掩码:
masked_img = cv2.bitwise_and(img, img, mask = mask)

2.文本检测:
文本区域以白色括起来,可以通过应用合适的阈值再次隔离。(您可能需要应用一些统计度量来计算阈值)
# Applying threshold at 220 on green channel of 'masked_img'
result = cv2.threshold(masked_img[:,:,1],220,255,cv2.THRESH_BINARY)[1]

备注:
过滤等高线。
# Function to extract rectangular contours above a certain area
def extract_rect(contours, area_threshold):
rect_contours = []
for c in contours:
if cv2.contourArea(c) > area_threshold:
perimeter = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.02*perimeter, True)
if len(approx) == 4:
cv2.drawContours(image, [approx], 0, (0,255,0),2)
rect_contours.append(c)
return rect_contours使用统计值(均值、中值等)进行的
https://stackoverflow.com/questions/72290119
复制相似问题