首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用OpenCV检测纸板箱及纸箱上的文字

用OpenCV检测纸板箱及纸箱上的文字
EN

Stack Overflow用户
提问于 2022-05-18 13:28:15
回答 2查看 596关注 0票数 1

我想数纸箱和阅读一个特定的标签,其中将只包含3个字,白色背景在传送带使用OpenCV和Python。附件是我用来做实验的图像。到目前为止的问题是,由于噪声,我无法检测到整个框,如果我试图在x,y,w,h=cv2中检查w和h,那么它只需过滤掉文本。在这种情况下,ABC写在方框上。此外,这个盒子已经检测到顶部和底部都有尖峰,我不知道如何过滤。

下面是我正在使用的代码

代码语言:javascript
运行
复制
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,如果你能找到一些时间来回答。

代码语言:javascript
运行
复制
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()

链接到视频: https://www.storyblocks.com/video/stock/boxes-and-packages-move-along-a-conveyor-belt-in-a-shipment-factory-a-few-blank-boxes-for-your-custom-graphics-lmgxtwq

问题:

  1. 如何100%确定所绘制的矩形是否实际上位于框的顶部而不是腰带或其他地方。
  2. 能否告诉我如何使用您在原始答案中提供的函数用于这个新的视频代码中的其他框。
  3. 是正确的方法,可以再次将蒙面帧转换为灰色,再找到轮廓来绘制矩形。或者有一种更有效的方法。
  4. ,这段代码的最终版本是在raspberry pi上运行的。那么我们能做些什么来优化代码的performance.

许多人再次感谢你们的时间。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-05-19 18:23:33

你的补充问题需要一个单独的答案:

1.如果绘制的矩形实际上在盒子的顶部而不是腰带或其他地方,我们如何100%确定?

为了这个目的,我选择了HSV颜色空间的

  • PRO:通道。灰色,白色和黑色的阴影(在传送带上)在这个通道是中性的。盒的棕色是对比,可以很容易地分割使用Otsu阈值。Otsu算法在没有用户input.
  • CON的情况下找到最佳阈值,当盒子与传送带

的颜色相同时,可能会遇到问题。

2.请您告诉我如何使用您在原始答案中提供的函数用于此新代码中用于视频.的其他框。

如果您希望使用边缘检测来查找框,而不使用颜色信息,则

  • PRO:很有可能获得许多不需要的边缘。通过使用extract_rect()函数,您可以过滤轮廓:

代码语言:javascript
运行
复制
1. have approximately 4 sides (quadrilateral)
2. are above certain area

  • CON如果你有超过4面的包裹/包裹/袋子,你可能需要改变这个.

3。它是否正确的方式再次转换蒙面框架为灰色,找到轮廓再次绘制一个矩形。或者有更有效的方法来做到这一点。

我觉得这是最好的方法,因为剩下的只是白色的文本区域。在我看来,应用高价值的阈值是最简单的想法。也许有一个更好的方法:)

(我不能回答第四项问题:)

票数 1
EN

Stack Overflow用户

发布于 2022-05-18 14:19:49

有两个步骤需要遵循:

1.框分割

我们可以假设没有背景变化,因为传送带是存在的。我们可以用不同的颜色空间分割盒子。在以下中,我使用了HSV颜色空间:

代码语言:javascript
运行
复制
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]

隐藏二值图像中最大的轮廓:

代码语言:javascript
运行
复制
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)

在原始图像上应用掩码:

代码语言:javascript
运行
复制
masked_img = cv2.bitwise_and(img, img, mask = mask)

2.文本检测:

文本区域以白色括起来,可以通过应用合适的阈值再次隔离。(您可能需要应用一些统计度量来计算阈值)

代码语言:javascript
运行
复制
# Applying threshold at 220 on green channel of 'masked_img'
result = cv2.threshold(masked_img[:,:,1],220,255,cv2.THRESH_BINARY)[1]

备注:

  1. 代码是为共享映像编写的。对于不同大小的盒子,您可以使用大约4 vertices/sides.

过滤等高线。

代码语言:javascript
运行
复制
# 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

使用统计值(均值、中值等)进行的

  1. 实验寻找检测文本区域的最佳阈值。
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72290119

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档