无法从轮廓正确裁剪Python ROI

问题描述

在回答这个问题之前,大家好,我已经搜索herehere toohere

我正在使用python代码检测图像中的叶子,使用轮廓查找,然后找出最大的轮廓,该部分效果最佳,但是然后我只希望图像的叶子部分而跳过图像的其余部分为了避免在输出结果中出现不必要的内容,该链接中的某些方法建议使用边框,但这仍会在图像中包含额外的内容,因为形状不是矩形,而是不规则的,已附加了样本

A sample image of mango leaf

下面的代码

import cv2
import numpy as np

img = cv2.imread("blob.jpg",-1)

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

thresh = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,101,3)

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
blob = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(9,9))
blob = 255 - cv2.morphologyEx(blob,cv2.MORPH_CLOSE,kernel)

cnts = cv2.findContours(blob,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

if len(cnts) == 2:
    cnts = cnts[0]
else:
    cnts = cnts[1]
    
big_contour = max(cnts,key = cv2.contourArea)

blob_area_thresh = 1000
blob_area = cv2.contourArea(big_contour)
if blob_area < blob_area_thresh:
    print("Leaf is Too Small")
else:
    #problem starts from here . i tested big_contour is just perfect by drawing on actual image
    mask = np.zeros_like(img)
    cv2.drawContours(mask,big_contour,-1,-1) 
    out = np.zeros_like(img) 
    out[mask == 255] = img[mask == 255]
    cv2.imwrite('output.jpg',out)

现在的问题是我得到的图像是黑色的,什么也没有裁剪所有黑色像素

解决方法

轮廓出现问题,因为它的叶子没有循环,因为右边的叶子末端不在图像中。

当我尝试填充轮廓以使用其创建蒙版时,您会看到

 cv2.fillPoly(mask,pts =[big_contour],color=(255,255,255))

它没有填满叶子。

enter image description here

但是我尝试了一些虽然不完美的尝试,并且还保留了一些背景,但是却使叶子变长了一部分。

import cv2
import numpy as np

img = cv2.imread("96Klg.jpg",-1)

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

thresh = cv2.adaptiveThreshold(gray,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,101,3)

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
blob = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel)

#kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(9,9))
#blob = 255 - cv2.morphologyEx(blob,cv2.MORPH_CLOSE,kernel)

cnts = cv2.findContours(blob,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

if len(cnts) == 2:
    cnts = cnts[0]
else:
    cnts = cnts[1]
    
big_contour = max(cnts,key = cv2.contourArea)
blob_area_thresh = 1000
blob_area = cv2.contourArea(big_contour)
if blob_area < blob_area_thresh:
    print("Leaf is Too Small")
else:
    #problem starts from here . i tested big_contour is just perfect by drawing on actual image
    mask = np.ones_like(img)
    mask.fill(255)
    cv2.fillPoly(mask,color=(0,0))

    #cv2.drawContours(mask,big_contour,-1,(255,255),1) 
    out = np.zeros_like(img) 
    out[mask == 255] = img[mask == 255]
    

    

width = int(gray.shape[1] * 0.25)
height = int(gray.shape[0] * 0.25)
dim = (width,height)
# resize image
resized = cv2.resize(out,dim,interpolation = cv2.INTER_AREA)
resizedmask = cv2.resize(mask,interpolation = cv2.INTER_AREA)

cv2.imshow('gray',resized)
cv2.imshow('out',resizedmask)

输出 enter image description here