Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python&;OpenCV:如何裁剪半成型边界框_Python_Opencv_Computer Vision_Bounding Box_Vision - Fatal编程技术网

Python&;OpenCV:如何裁剪半成型边界框

Python&;OpenCV:如何裁剪半成型边界框,python,opencv,computer-vision,bounding-box,vision,Python,Opencv,Computer Vision,Bounding Box,Vision,我有一个为无网格表创建网格线的脚本: 在脚本之前: 在脚本之后: 是否有一种简单的方法,使用OpenCV裁剪“后脚本”图像,使其仅包含四边边界框?样本输出: 编辑: 我目前正在研究一种解决方案,可以找到第一条/最后一条垂直/水平方向的全黑像素线。它可以工作,但我想知道是否还有更优雅的东西。在Python/OpenCV中,有一种方法可以做到这一点,即从除最大轮廓外的所有轮廓中获取最小和最大x和y 输入: 导入cv2 将numpy作为np导入 #读取图像 img=cv2.imread('te

我有一个为无网格表创建网格线的脚本:

在脚本之前:

在脚本之后:

是否有一种简单的方法,使用OpenCV裁剪“后脚本”图像,使其仅包含四边边界框?样本输出:

编辑:


我目前正在研究一种解决方案,可以找到第一条/最后一条垂直/水平方向的全黑像素线。它可以工作,但我想知道是否还有更优雅的东西。

在Python/OpenCV中,有一种方法可以做到这一点,即从除最大轮廓外的所有轮廓中获取最小和最大x和y

输入:

导入cv2
将numpy作为np导入
#读取图像
img=cv2.imread('test_table.png'))
hh,ww=img.shape[:2]
#变灰
灰色=cv2.CVT颜色(img,cv2.COLOR\U BGR2GRAY)
#门槛
thresh=cv2.threshold(灰色,128255,cv2.thresh_二进制)[1]
#裁剪1像素并添加1像素白色边框,以确保外部白色区域不被视为小轮廓
thresh=thresh[1:hh-1,1:ww-1]
thresh=cv2.copyMakeBorder(thresh,1,1,1,borderType=cv2.BORDER_常量,值=(255255))
#获得轮廓
轮廓=cv2.找到的轮廓(阈值、cv2.RETR\u列表、cv2.链近似值\u简单)
等高线=等高线[0]如果len(等高线)==2其他等高线[1]
大轮廓=最大(轮廓,关键点=cv2.轮廓面积)
#从大于图像大小一半的所有边界框中获取最小值和最大值x和y
面积_阈值=hh*ww/2
xmin=ww
ymin=hh
xmax=0
ymax=0
对于轮廓中的cntr:
面积=cv2。轮廓面积(cntr)
如果面积<面积\阈值:
x、 y,w,h=cv2.boundingRect(cntr)
xmin=x如果(xxmax)否则xmax
ymax=y+h-1如果(y+h-1>ymax)其他ymax
#绘制边界框
bbox=img.copy()
矩形(bbox,(xmin,ymin),(xmax,ymax),(0,0,255),2)
#在边界框处裁剪img,但在四周添加2以保留黑线
结果=img[ymin-3:ymax+3,xmin-3:xmax+3]
#保存结果
cv2.imwrite('test_table_bbox.png',bbox)
cv2.imwrite('test\u table\u trimmed.png',result)
#显示结果
cv2.imshow(“脱粒”,脱粒)
cv2.imshow(“bbox”,bbox)
cv2.imshow(“结果”,结果)
cv2.等待键(0)
cv2.destroyAllWindows()

输入时所有边界框的边界框:

修剪图像:

注意:我知道已经有一个公认的答案,但我想提供一个更简单的版本

基本上,首先找到图像中每个形状(每个单元)的轮廓,这些形状的面积大于所选数字,可以滤除任何噪声

在等高线中循环,找到最小和最大的x和y坐标。使用这4个点,我们可以将图像中四个坐标内的像素保存到一个单独的数组中,用白色填充原始图像,然后将表格重新绘制到图像上

守则:

import cv2

img = cv2.imread("table.png")
h, w, _ = img.shape

x1, y1 = w, h
x2, y2 = 0, 0

contours, _ = cv2.findContours(cv2.Canny(img, 0, 0), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

for cnt in contours:
    if cv2.contourArea(cnt) > 1000:
        x1 = min(cnt[..., 0].min(), x1)
        y1 = min(cnt[..., 1].min(), y1)
        x2 = max(cnt[..., 0].max(), x2)
        y2 = max(cnt[..., 1].max(), y2)

pad = 2
x1 -= pad
y1 -= pad
x2 += pad * 2
y2 += pad * 2

table = img[y1:y2, x1:x2].copy()

img.fill(255)
img[y1:y2, x1:x2] = table
cv2.imshow("lined_table.png", img)
cv2.waitKey(0)
输出:

说明:

  • 导入opencv模块并读取图像。获取图像的尺寸,并为表格的第一个角点和最后一个角点定义临时坐标:
  • 获取图像的轮廓,循环遍历每个轮廓,过滤出面积小于1000的轮廓:
  • 更新表格第一个角点和最后一个角点的坐标值:
  • 根据线的宽度,在每个坐标周围应用焊盘:
  • 根据找到的x和y坐标,将图像的一部分复制到变量中,清空图像,然后将表格重新绘制到图像上。最后,显示图像:
  • import cv2
    
    img = cv2.imread("table.png")
    h, w, _ = img.shape
    
    x1, y1 = w, h
    x2, y2 = 0, 0
    
    contours, _ = cv2.findContours(cv2.Canny(img, 0, 0), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
    for cnt in contours:
        if cv2.contourArea(cnt) > 1000:
            x1 = min(cnt[..., 0].min(), x1)
            y1 = min(cnt[..., 1].min(), y1)
            x2 = max(cnt[..., 0].max(), x2)
            y2 = max(cnt[..., 1].max(), y2)
    
    pad = 2
    x1 -= pad
    y1 -= pad
    x2 += pad * 2
    y2 += pad * 2
    
    table = img[y1:y2, x1:x2].copy()
    
    img.fill(255)
    img[y1:y2, x1:x2] = table
    cv2.imshow("lined_table.png", img)
    cv2.waitKey(0)
    
    import cv2
    
    img = cv2.imread("table.png")
    h, w, _ = img.shape
    
    x1, y1 = w, h
    x2, y2 = 0, 0
    
    contours, _ = cv2.findContours(cv2.Canny(img, 0, 0), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
    for cnt in contours:
        if cv2.contourArea(cnt) > 999:
    
            x1 = min(cnt[..., 0].min(), x1)
            y1 = min(cnt[..., 1].min(), y1)
            x2 = max(cnt[..., 0].max(), x2)
            y2 = max(cnt[..., 1].max(), y2)
    
    pad = 2
    x1 -= pad
    y1 -= pad
    x2 += pad * 2
    y2 += pad * 2
    
    table = img[y_1:y_2, x_1:x_2].copy()
    
    img.fill(255)
    img[y_1:y_2, x_1:x_2] = table
    cv2.imwrite("lined_table.png", img)
    cv2.waitKey(0)