简体   繁体   English

无法正确检测和遮盖轮廓

[英]Unable to detect and mask a contour properly

I am trying to detect and mask the second largest contour in an image as shown in Figure 1 (with red outline). 我正在尝试检测并掩盖图像中第二大轮廓,如图1所示(带有红色轮廓)。 However, I am unable to detect the full second largest contour in the image. 但是,我无法检测到图像中的第二大轮廓。 I am getting what is shown in Figure 2. Below is my code. 我将得到如图2所示的内容。下面是我的代码。 Please can someone kindly advise. 请有人请指教。

im = cv2.imread('F:\EA-358-4-1.4\ea-580.png')                                                         # Reading image
blur = cv2.GaussianBlur(im,(5,5),cv2.BORDER_DEFAULT)                                             # Smoothing image
img = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)                                                     # Converting to greyscale image
ret, thresh = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
_, contours,_ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)                 # Finding contours, hierarchy et al.
print(len(contours))

# Masking image and drawing contour
cnt = contours 
mask = np.zeros_like(im)                                                                         # Masking the contour
second_largest_cnt = sorted(cnt, key = cv2.contourArea, reverse = True)[1]                          # Dtermine the second largest contour
cv2.drawContours(mask,[second_largest_cnt],-1,(255,255,255),-1)                                    # Drawing the detected contour

# Copying mask of detected contour unto original image  and canning edge detection
out = mask.copy()                                                                                # Copying the mask nto the original image
out[mask == 255] = im[mask == 255]                                                  
canny = feature.canny(out[:, :, 0],sigma=1,low_threshold=5,high_threshold=10)                    # Detecting the egeds of the image

plt.subplot(121),plt.imshow(canny,cmap='gray')
plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(out,cmap='gray')
plt.xticks([]),plt.yticks([])

Figure 1 图1

输入图像

Figure 2 图2

到目前为止输出图像

Figure 3 图3

所需的输出图像

Updated code I have updated the code in accordance with @HansHirse suggestion but I coundn't get a any results. 更新的代码我已经按照@HansHirse的建议更新了代码,但是我无法获得任何结果。

im = cv2.imread('F:\EA-358-4-1.4\ea-580.png',cv2.IMREAD_GRAYSCALE)
#new = im[:,:,1] 
mask = np.zeros_like(im)

th3 = cv2.adaptiveThreshold(im,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,201,-1)

kernel = np.ones((5,5),np.uint8)
opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(7,7)),kernel)
dilate = cv2.dilate(mask,cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(11,11)))

img = im-mask

thresh = cv2.threshold(img,0,255,cv2.THRESH_OTSU)

opening = cv2.morphologyEx(img, cv2.MORPH_CLOSE, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(7,7)),kernel)

_, contours,_ = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

cv2.drawContours(im,contours,-1,255,1)
cv2.imshow('im',im)

Since I'm (still) not very familiar with OpenCV in Python, I'll provide my solution using C++ OpenCV. 由于我(仍然)对Python中的OpenCV不太熟悉,因此我将使用C ++ OpenCV提供解决方案。 I commented every line, to make porting to Python as easy as possible. 我评论了每一行,以尽可能轻松地移植到Python。

// Read input image.
cv::Mat img = cv::imread("e9dzM.png", cv::IMREAD_GRAYSCALE);

// Initialize mask.    
cv::Mat mask = img.clone();

// Adaptive thresholding, 201 x 201 neighbourhood. 
cv::adaptiveThreshold(img, mask, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, cv::THRESH_BINARY, 201, -1);

// Morphological opening, 7 x 7 ellipsoid.
cv::morphologyEx(mask, mask, cv::MORPH_OPEN, cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(7, 7)));

// Morphological dilating, 7 x 7 ellipsoid.
cv::dilate(mask, mask, cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(11, 11)));

// Temporary image: Subtract ring like structure from original image.
cv::Mat temp = img - mask;

// Plain thresholding using Otsu method.
cv::threshold(temp, temp, 0, 255, cv::THRESH_OTSU);

// Morphological closing, 7 x 7 ellipsoid.
cv::morphologyEx(temp, temp, cv::MORPH_CLOSE, cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(7, 7)));

// Find contours in temporary image.
std::vector<std::vector<cv::Point>> contours;
cv::findContours(temp, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);

// Draw found contours in input image.
cv::drawContours(img, contours, -1, cv::Scalar(255), 1);

// Save image.
cv::imwrite("output.png", img);

You get the following output image: 您将获得以下输出图像:

输出图像

This solution might work for specific images as provided by you. 此解决方案可能适用于您提供的特定图像。 I highly doubt, that this code can be used for more general problems. 我非常怀疑,此代码可用于更一般的问题。 Please keep that in mind. 请记住这一点。

似乎有些图像的照明不均匀,因此我使用初始代码对某些图像应用了自适应阈值,并且效果很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM