open-cv轮廓检测

open-cv的轮廓检测矩形拟合 下图中如何实现最大矩形的检测呢

  1. img


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()

img

img



```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)


望采纳,您的采纳就是对我最大的动力,谢谢!!!

img

直接取外轮廓

滤波后边缘检测,提取轮廓

直接用CV的API:cv2.maxAreaRect(c)

img

img

img

把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

如帮助到您解决疑惑,记得点个采纳,谢谢合作

阈值处理 然后寻找外部轮廓,直接最大外接矩形