噪声图像上的 Opencv 矩形检测

Opencv rectangle detection on noisy image

一个问题,当图像碰到噪声线和其他形状时,是否可以检测到图像上的矩形 这是我检测图像轮廓的功能:

def findContours(img_in):
w, h, c = img_in.shape  # img_in is the input image
resize_coeff = 0.25
img_in = cv2.resize(img_in,(int(resize_coeff * h), int(resize_coeff * w)))
img_in = ip.findObjects(img_in)




blr = cv2.GaussianBlur(img_in, (9, 9), 0)
img = cv2.Canny(blr, 50, 250, L2gradient=False)

kernel = np.ones((5, 5), np.uint8)
img_dilate = cv2.dilate(img, kernel, iterations=1)
img = cv2.erode(img_dilate, kernel, iterations=1)
contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
max_index, max_area = max(enumerate([cv2.contourArea(x) for x in contours]), key=lambda x: x[1])
max_contour = contours[max_index]
img_out = cv2.resize(img, (int(resize_coeff * h), int(resize_coeff * w)))
cv2.drawContours(img_in, [max_contour], 0, (0, 0, 255), 2)
re.rectangle(img, [max_contour])
cv2.imshow("test",img_in)
cv2.imshow("test1",img)

cv2.waitKey()
return img

我得到了这个结果:

我想要的结果:

当我使用形状检测时,我得到的结果是它有 15 个角度而不是四个。函数:

def rectangle(img, contours):
for contour in contours:
    approx = cv2.approxPolyDP(contour, 0.01 * cv2.arcLength(contour, True), True)
    print(len(approx))
    x = approx.ravel()[0]
    y = approx.ravel()[1] - 5

    if len(approx) == 4:
        print("Rect")
        x, y, w, h = cv2.boundingRect(approx)
        aspectRatio = float(w) / h
        print(aspectRatio)
        cv2.putText(img, "rectangle", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))

编辑: 原图:

如果您可以消除该形状周围的噪音会怎么样?我认为您的面具适合进行更多处理:

import numpy as np
import sys
import cv2

# Load the mask
dir = sys.path[0]
im = cv2.imread(dir+'/img.png')
H, W = im.shape[:2]

# Make gray scale image
gry = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)

# Make binary image
bw = cv2.threshold(gry, 127, 255, cv2.THRESH_BINARY)[1]
bw = ~bw

# Focuse on edges
bw = cv2.erode(bw, np.ones((5, 5)))

# Use flood fill to remove noise
cv2.floodFill(bw, np.zeros((H+2, W+2), np.uint8), (0, 0), 0)
bw = cv2.medianBlur(bw, 7)

# Remove remained noise with another flood fill
nonRectArea = bw.copy()
cv2.floodFill(nonRectArea, np.zeros((H+2, W+2), np.uint8), (W//2, H//2), 0)
bw[np.where(nonRectArea == 255)] = 0

# Find contours and sort them by width
cnts, _ = cv2.findContours(bw, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnts.sort(key=lambda p: cv2.boundingRect(p)[2], reverse=True)

# Find biggest blob
x, y, w, h = cv2.boundingRect(cnts[0])
cv2.rectangle(im, (x, y), (x+w, y+h), 127, 1)

# Save output
cv2.imwrite(dir+'/img_1.png', im)
cv2.imwrite(dir+'/img_2.png', bw)
cv2.imwrite(dir+'/img_3.png', nonRectArea)