使用掩码中找到的轮廓从原始图像中获取 ROI 的有效方法
Efficient way to get ROI from original image using contours found in mask
我要完成的任务是通过在图像的蒙版中找到轮廓来隔离图像中的某些对象,然后获取每个轮廓(基于区域)并将其隔离,然后使用此轮廓来裁剪原始图像中的相同区域,以获得该区域的像素值,
例如:
我写的代码是为了只得到一个轮廓,然后用原始像素值将其隔离:
import cv2
import matplotlib.pyplot as plt
import numpy as np
image = cv2.imread("./xxxx/xx.png")
mask = cv2.imread("./xxxx/xxx.png")
# making them the same size (function I wrote)
image, mask = resize_two_images(image,mask)
#grayscalling the mask (using cv2.cvtCOLOR)
mask = to_gray(mask)
# a function I wrote to display images using plt
display(image,"image: original image")
display(mask,"mask: mask of the image")
th, mask = cv2.threshold(mask, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
contours, hierarchy = cv2.findContours(
mask, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)
for i in range(len(contours)):
hier = hierarchy[0][i][3]
cnt = contours[i]
cntArea = cv2.contourArea(cnt)
if 1000 < cntArea < 2000:
break
#breaking because I'm just keeping the first contour that fills the condtion
# Creating two zero numpy array
img1 = np.zeros(image.shape, dtype=np.uint8)
img2 = img1.copy()
# drawing the contour which will basiclly give the edges of the object
cv2.drawContours(img1, [cnt], -1, (255,255,255), 2)
# drawing indise the the edges
cv2.fillPoly(img2, [cnt], (255,255,255))
# adding the filled poly with the drawn contour gives bigger object that
# contains the both the edges and the insides of the object
img1 = img1 + img2
display(img1,"img1: final")
res = np.bitwise_and(img1,image)
display(res,"res : the ROI with original pixel values")
#cropping the ROI (the object we want)
x,y,w,h = cv2.boundingRect(cnt)
# (de)increased values in order to get nonzero borders or lost pixels
res1 = res[y-1:y+h+1,x-1:x+w+1]
display(res1,"res1: cropped ROI")
问题是的,我找到了一种只针对一个轮廓的方法,但是有没有另一种方法可以更有效地做到这一点,因为每张图像可能数百个轮廓。
目前尚不清楚您是希望只输出一张包含所有 selected 轮廓的图像,还是每个 selected 轮廓输出一张单独的图像。
您可以高效地获得包含所有 selected 轮廓的图像。
首先 select 所有你想要处理的轮廓,然后,绘制所有用白色填充的轮廓,这样你就可以用它作为蒙版,然后蒙版原始图像:
selected_contours = [c for c in contours if cv2.contourArea(c) >= 2000]
# the last parameter, negative line thickness, fills the contour
mask = cv2.drawContours(img1, selected_contours, -1, (255,255,255), -1)
res = np.bitwise_and(mask,image)
我要完成的任务是通过在图像的蒙版中找到轮廓来隔离图像中的某些对象,然后获取每个轮廓(基于区域)并将其隔离,然后使用此轮廓来裁剪原始图像中的相同区域,以获得该区域的像素值, 例如:
我写的代码是为了只得到一个轮廓,然后用原始像素值将其隔离:
import cv2
import matplotlib.pyplot as plt
import numpy as np
image = cv2.imread("./xxxx/xx.png")
mask = cv2.imread("./xxxx/xxx.png")
# making them the same size (function I wrote)
image, mask = resize_two_images(image,mask)
#grayscalling the mask (using cv2.cvtCOLOR)
mask = to_gray(mask)
# a function I wrote to display images using plt
display(image,"image: original image")
display(mask,"mask: mask of the image")
th, mask = cv2.threshold(mask, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
contours, hierarchy = cv2.findContours(
mask, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)
for i in range(len(contours)):
hier = hierarchy[0][i][3]
cnt = contours[i]
cntArea = cv2.contourArea(cnt)
if 1000 < cntArea < 2000:
break
#breaking because I'm just keeping the first contour that fills the condtion
# Creating two zero numpy array
img1 = np.zeros(image.shape, dtype=np.uint8)
img2 = img1.copy()
# drawing the contour which will basiclly give the edges of the object
cv2.drawContours(img1, [cnt], -1, (255,255,255), 2)
# drawing indise the the edges
cv2.fillPoly(img2, [cnt], (255,255,255))
# adding the filled poly with the drawn contour gives bigger object that
# contains the both the edges and the insides of the object
img1 = img1 + img2
display(img1,"img1: final")
res = np.bitwise_and(img1,image)
display(res,"res : the ROI with original pixel values")
#cropping the ROI (the object we want)
x,y,w,h = cv2.boundingRect(cnt)
# (de)increased values in order to get nonzero borders or lost pixels
res1 = res[y-1:y+h+1,x-1:x+w+1]
display(res1,"res1: cropped ROI")
问题是的,我找到了一种只针对一个轮廓的方法,但是有没有另一种方法可以更有效地做到这一点,因为每张图像可能数百个轮廓。
目前尚不清楚您是希望只输出一张包含所有 selected 轮廓的图像,还是每个 selected 轮廓输出一张单独的图像。 您可以高效地获得包含所有 selected 轮廓的图像。 首先 select 所有你想要处理的轮廓,然后,绘制所有用白色填充的轮廓,这样你就可以用它作为蒙版,然后蒙版原始图像:
selected_contours = [c for c in contours if cv2.contourArea(c) >= 2000]
# the last parameter, negative line thickness, fills the contour
mask = cv2.drawContours(img1, selected_contours, -1, (255,255,255), -1)
res = np.bitwise_and(mask,image)