检测噪声图像中的轮廓

问题描述 投票:0回答:1

我试图检测图片中模具边缘的轮廓,但图像的右上角有一个障碍物

原图:https://pan.quark.cn/s/3adddd6e1d87

这是我迄今为止尝试过的:

import numpy as np
import cv2
import time
import glob
import os

def process_img(img):
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    gray = cv2.GaussianBlur(gray, (15, 15), 1)
    ret, th1 = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
    
    #th1 = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 17, 2)

    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    th1 = cv2.morphologyEx(th1, cv2.MORPH_OPEN, kernel)
    th1 = cv2.morphologyEx(th1, cv2.MORPH_CLOSE, kernel)

    edge = cv2.Canny(th1, 150, 255)
    return th1, img, edge


def get_roi(img, binary):
    """
    img: source pic
    binary: canny
    """
    # 寻找轮廓
    contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    max_area = 0
    temp = 0
    for cnt in range(len(contours)):
        xxx = cv2.contourArea(contours[cnt])
        if xxx > max_area:
            max_area = xxx
            temp = cnt

    series = contours[temp]
    x, y, w, h = cv2.boundingRect(series)
    p = cv2.arcLength(series, True)
    cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
    cv2.drawContours(img, [series], 0, (255, 0, 255), 2)

    return img


def die_select(img: np.ndarray, img_template: np.ndarray = None) -> np.ndarray:
    th1, img, edge = process_img(img)
    img = get_roi(img, edge)
    return img

到目前为止,我的结果如下:

picture 1

我想要的结果是这样的: picture 2

python opencv contour edge-detection
1个回答
0
投票

这是我的方法,首先读取图像并转换为灰度。使用 OTSU 阈值处理 来获取感兴趣的区域。之后,获取轮廓并获取最大面积,这应该对应于对象:

im = cv2.imread("example.png") # read the iamge
imGray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) # convert to gray
imGray = cv2.equalizeHist(imGray) # equalize hist, maybe not necessary
imOTSU = cv2.threshold(imGray, 0, 255, cv2.THRESH_OTSU+cv2.THRESH_BINARY_INV)[1] # get otsu with inner as positive
imOTSUOpen =  cv2.morphologyEx(imOTSU, cv2.MORPH_OPEN, np.ones((3,3), np.uint8)) # open
contours, _ = cv2.findContours(imOTSUOpen, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # get contours
largestContour = max(contours, key = cv2.contourArea) # get the largest
# get X, Y coordinates
X, Y = largestContour.T
X = X[0]
Y = Y[0]

从这里开始,我尝试了分位数,并成功识别了左上角和右下角,这就是边界矩形所需的全部:

plt.figure() # new fiugre
plt.imshow(im) # show image
plt.axvline(min(X)) # draw verticle line at minimum x
plt.axhline(max(Y)) # draw horizontal line at minimum y
upperLeft = (int(np.quantile(X, 0.1)), int(np.quantile(Y, 0.25))) # get quantiles as corner
lowerRight = (int(np.quantile(X, 0.55)), int(np.quantile(Y, 0.9))) # get quantiles as corner
plt.scatter(upperLeft[0], upperLeft[1]) # scatter the corner
plt.scatter(lowerRight[0], lowerRight[1]) # scatter the corner

剧情是这样的:

现在你有了这个,绘制矩形就很容易了:

cv2.rectangle(im, (upperLeft[0], upperLeft[1]), (lowerRight[0], lowerRight[1]), (0, 255, 0), 2) # draw rectangle as green
cv2.imwrite("exampleContoured.png", im)

我仍然会检查堆栈,应该有很多突出轮廓的例子,并且肯定有更强大的方法来解决这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.