open-cv的轮廓检测矩形拟合 下图中如何实现最大矩形的检测呢
import cv2 as cv
import numpy as np
img_path = "/home/LTL/Desktop/20220719171125.png"
img_np = cv.imread(img_path)
ret, thresh1 = cv.threshold(img_np, 80, 255, cv.THRESH_BINARY)
np_zeros = np.ones(thresh1.shape[0:2]) * 255
index_1 = np.where(thresh1[:, :, 0] == 0)
index_2 = np.where(thresh1[:, :, 1] == 0)
index_3 = np.where(thresh1[:, :, 1] == 0)
np_zeros[index_1[0], index_1[1]] = 0
np_zeros[index_2[0], index_2[1]] = 0
np_zeros[index_3[0], index_3[1]] = 0
contour_list, _ = cv.findContours(np_zeros.astype(np.uint8), cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
contour_area_list = list(map(lambda x: cv.contourArea(x), contour_list))
contour_list = list(filter(lambda x: 100 < cv.contourArea(x) < img_np.shape[0] * img_np.shape[1] // 2, contour_list))
result_xywh = []
result_poly_point = []
contour_list.sort(key=lambda x: cv.contourArea(x), reverse=True)
for contour_i, contour in enumerate(contour_list[0:1]):
contour_area = cv.contourArea(contour)
x, y, w, h = cv.boundingRect(contour)
poly_point_list = contour[:, 0, :].ravel().tolist()
poly_point = np.int0(poly_point_list).reshape((-1, 1, 2))
result_poly_point.append(poly_point)
cv.rectangle(img_np, (x, y), (x + w, y + h), (255, 255, 0), 2)
cv.imshow('', img_np)
cv.waitKey()
cv.destroyAllWindows()
```python
import cv2
import numpy as np
import math
"""
1.图片得到极坐标直线
"""
img = cv2.imread('projection.png')
img1 = img.copy()
img2 = img.copy()
# img = cv2.GaussianBlur(img, (3, 3), 0)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150, apertureSize=3)
lines = cv2.HoughLines(edges, 1, np.pi / 180, 110)
"""
2.极坐标直线转为直角坐标系直线
"""
for line in lines:
rho = line[0][0]
theta = line[0][1]
a = np.cos(theta)
b = np.sin(theta)
x0 = a * rho
y0 = b * rho
x1 = int(x0 + 1000 * (-b))
y1 = int(y0 + 1000 * (a))
x2 = int(x0 - 1000 * (-b))
y2 = int(y0 - 1000 * (a))
cv2.line(img1, (x1, y1), (x2, y2), (0, 0, 255), 2)
"""
3.通过阈值过滤多余直线
"""
"""
cv2.HoughLinesP(image, rho, theta, threshold, lines, minLineLength, maxLineGap)
src:输入图像,必须8-bit的灰度图像
rho:生成极坐标时候的像素扫描步长
theta:生成极坐标时候的角度步长
threshold:阈值,只有获得足够交点的极坐标点才被看成是直线
lines:输出的极坐标来表示直线
minLineLength:最小直线长度,比这个短的线都会被忽略。
maxLineGap:最大间隔,如果小于此值,这两条直线 就被看成是一条直线。
"""
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 30, 300, 12)
for line in lines:
x1 = line[0][0]
y1 = line[0][1]
x2 = line[0][2]
y2 = line[0][3]
cv2.line(img2, (x1, y1), (x2, y2), (0, 255, 0), 2)
# cv2.imshow('houghlines3', img1)
cv2.imshow('edges', img2)
cv2.waitKey(0)
print(lines)
"""
4.求出出发点,终点的极值
"""
x1_min = min([line[0][0] for line in lines])
print("x1_min:" + str(x1_min))
y1_min = min([line[0][1] for line in lines])
print("y1_min:" + str(y1_min))
x2_max = max([line[0][2] for line in lines])
print("x2_max:" + str(x2_max))
y2_max = max([line[0][3] for line in lines])
print("y2_max:" + str(y2_max))
"""
5.消除坐标轴刻度干扰
(1)由于刻度线干扰,将极值点向内缩小一定范围,在该范围内取均值,来更精确画线,这里选择20(刻度线大约宽度)
(2)所有边框向内缩进2,消除坐标轴干扰
"""
x1_min_finally = int(math.ceil(np.mean(list(filter(lambda n:n >= x1_min and n < x1_min + 10,[line[0][0] for line in lines]))))) + 2
y1_min_finally = int(math.ceil(np.mean(list(filter(lambda n:n >= y1_min and n < y1_min + 10,[line[0][1] for line in lines]))))) + 2
x2_max_finally = int(math.floor(np.mean(list(filter(lambda n:n <= x2_max and n > x2_max - 10,[line[0][2] for line in lines]))))) - 2
y2_max_finally = int(math.floor(np.mean(list(filter(lambda n:n <= y2_max and n > y2_max - 10,[line[0][3] for line in lines]))))) - 2
print("x1_min_finally:" + str(x1_min_finally))
print("y1_min_finally:" + str(y1_min_finally))
print("x2_max_finally:" + str(x2_max_finally))
print("y2_max_finally:" + str(y2_max_finally))
"""
6.再次画线
"""
img2 = img.copy()
cv2.line(img2, (x1_min_finally, y1_min_finally), (x2_max_finally, y1_min_finally), (0, 255, 0), 2)
cv2.line(img2, (x1_min_finally, y2_max_finally), (x2_max_finally, y2_max_finally), (0, 255, 0), 2)
cv2.line(img2, (x1_min_finally, y1_min_finally), (x1_min_finally, y2_max_finally), (0, 255, 0), 2)
cv2.line(img2, (x2_max_finally, y1_min_finally), (x2_max_finally, y2_max_finally), (0, 255, 0), 2)
cv2.imshow('edges', img2)
cv2.waitKey(0)
望采纳,您的采纳就是对我最大的动力,谢谢!!!
直接取外轮廓
滤波后边缘检测,提取轮廓
直接用CV的API:cv2.maxAreaRect(c)
把min换成max,多余的其他轮廓检测部分去掉
#找最大矩形
rect = cv2.maxAreaRect(c)
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawCounters(img, [box], 0 ,(0,0,255),3)
详情可参考:
http://t.csdn.cn/XKGhu
如帮助到您解决疑惑,记得点个采纳,谢谢合作
阈值处理 然后寻找外部轮廓,直接最大外接矩形