如何裁剪轮廓的内部区域?
image
image-processing
opencv
python
15
0

我正在处理视网膜眼底图像。图像由黑色背景上的圆形视网膜组成。使用OpenCV,我设法获得了一个围绕整个圆形视网膜的轮廓。我需要的是从黑色背景中裁剪出圆形视网膜。

参考资料:
Stack Overflow
收藏
评论
共 3 个回答
高赞 时间 活跃

在您的问题中尚不清楚,您是要实际裁剪轮廓中定义的信息还是要屏蔽与所选轮廓无关的信息。我将探讨两种情况下的处理方法。


掩盖信息

假设您在cv2.findContours上运行了cv2.findContours ,您将收到一个列出图像中所有可用轮廓的结构。我还假设您知道用来包围所需对象的轮廓索引 。假设将其存储在idx ,请首先使用cv2.drawContours将此轮廓的填充版本绘制到空白图像上,然后使用此图像索引到图像中以提取对象。该逻辑掩盖了所有不相关的信息,只保留了重要的信息-在所选轮廓中定义了重要信息。假设您的图像是存储在img的灰度图像,则执行此操作的代码应类似于以下内容:

import numpy as np
import cv2
img = cv2.imread('...', 0) # Read in your image
# contours, _ = cv2.findContours(...) # Your call to find the contours using OpenCV 2.4.x
_, contours, _ = cv2.findContours(...) # Your call to find the contours
idx = ... # The index of the contour that surrounds your object
mask = np.zeros_like(img) # Create mask where white is what we want, black otherwise
cv2.drawContours(mask, contours, idx, 255, -1) # Draw filled contour in mask
out = np.zeros_like(img) # Extract out the object and place into output image
out[mask == 255] = img[mask == 255]

# Show the output image
cv2.imshow('Output', out)
cv2.waitKey(0)
cv2.destroyAllWindows()

如果你真的想种...

如果要裁剪图像,则需要定义轮廓定义的区域的最小跨度边界框。您可以找到边界框的左上角和右下角,然后使用索引来裁剪出所需的内容。代码将与以前相同,但是将有一个附加的裁剪步骤:

import numpy as np
import cv2
img = cv2.imread('...', 0) # Read in your image
# contours, _ = cv2.findContours(...) # Your call to find the contours using OpenCV 2.4.x
_, contours, _ = cv2.findContours(...) # Your call to find the contours
idx = ... # The index of the contour that surrounds your object
mask = np.zeros_like(img) # Create mask where white is what we want, black otherwise
cv2.drawContours(mask, contours, idx, 255, -1) # Draw filled contour in mask
out = np.zeros_like(img) # Extract out the object and place into output image
out[mask == 255] = img[mask == 255]

# Now crop
(y, x) = np.where(mask == 255)
(topy, topx) = (np.min(y), np.min(x))
(bottomy, bottomx) = (np.max(y), np.max(x))
out = out[topy:bottomy+1, topx:bottomx+1]

# Show the output image
cv2.imshow('Output', out)
cv2.waitKey(0)
cv2.destroyAllWindows()

裁剪代码的工作原理是,当我们定义遮罩以提取轮廓所定义的区域时,我们还会找到定义轮廓左上角的最小水平和垂直坐标。同样,我们找到了定义轮廓的左下角的最大水平和垂直坐标。然后,我们使用这些坐标的索引来裁剪我们实际需要的内容。请注意,这会对蒙版图像进行裁切,该图像将除去除最大轮廓中包含的信息以外的所有内容。

注意与OpenCV 3.x

应该注意的是,以上代码假定您使用的是OpenCV2.4.x。请注意,在OpenCV 3.x中, cv2.findContours的定义已更改。具体来说,输出是一个三元素元组输出,其中第一个图像是源图像,而其他两个参数与OpenCV 2.4.x中的相同。因此,只需更改以上代码中的cv2.findContours语句即可忽略第一个输出:

_, contours, _ = cv2.findContours(...) # Your call to find contours
收藏
评论

这是一种非常简单的方法。用透明度遮罩图像。

Read the image

Make a grayscale version.

Otsu Threshold

Apply morphology open and close to thresholded image as a mask

Put the mask into the alpha channel of the input

Save the output


输入:

在此处输入图片说明

import cv2
import numpy as np


# load image as grayscale
img = cv2.imread('retina.jpeg')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# threshold input image using otsu thresholding as mask and refine with morphology
ret, mask = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU) 
kernel = np.ones((9,9), np.uint8)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)

# put thresh into 
result = img.copy()
result = cv2.cvtColor(result, cv2.COLOR_BGR2BGRA)
result[:, :, 3] = mask

# save resulting masked image
cv2.imwrite('retina_masked.png', result)


在此处输入图片说明

收藏
评论

这是裁剪矩形ROI的另一种方法。主要思想是使用Canny边缘检测来找到视网膜的边缘,找到轮廓,然后使用Numpy切片来提取ROI。假设您有一个这样的输入图像:

提取的ROI

import cv2

# Load image, convert to grayscale, and find edges
image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY)[1]

# Find contour and sort by contour area
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)

# Find bounding box and extract ROI
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    ROI = image[y:y+h, x:x+w]
    break

cv2.imshow('ROI',ROI)
cv2.imwrite('ROI.png',ROI)
cv2.waitKey()
收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题