Python&;OpenCV:如何裁剪半成型边界框
我有一个为无网格表创建网格线的脚本: 在脚本之前: 在脚本之后: 是否有一种简单的方法,使用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
我目前正在研究一种解决方案,可以找到第一条/最后一条垂直/水平方向的全黑像素线。它可以工作,但我想知道是否还有更优雅的东西。在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)
输出:
说明:
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)