简体   繁体   English

如何从图像中删除最大轮廓标记的 object 并将其另存为单独的图像?

[英]How to remove the object marked by the biggest contour from an image and save it as a separate image?

Our objective is to classify plants in a field based on its leaves.我们的目标是根据叶子对田野中的植物进行分类。 We have trained our model on segmented images (these images only have a leaf and black background).我们已经在分割图像上训练了我们的 model(这些图像只有叶子和黑色背景)。 But the live feed from the camera will look like this:但是来自摄像头的实时信息将如下所示:

在此处输入图像描述

So our idea is to find the biggest contour, separate the leaf marked by it and give it a black background.所以我们的想法是找到最大的轮廓,把它标记的叶子分开,给它一个黑色的背景。

最大轮廓标记

This is kinda what we are trying to achieve (except the small leaf popping in):这有点像我们正在努力实现的目标(除了弹出的小叶子):

在此处输入图像描述

Our approach was to draw a bounding box around the leaf and form a new separate frame.我们的方法是在叶子周围绘制一个边界框并形成一个新的单独框架。 This is our code:这是我们的代码:

def nothing(useless=None):
    pass

cv2.namedWindow("Mask")
cap = cv2.VideoCapture(0)

cv2.createTrackbar('R_l','Mask',26,255,nothing)
cv2.createTrackbar('G_l','Mask',46,255,nothing)
cv2.createTrackbar('B_l','Mask',68,255,nothing)

cv2.createTrackbar('R_h','Mask',108,255,nothing)
cv2.createTrackbar('G_h','Mask',138,255,nothing)
cv2.createTrackbar('B_h','Mask',155,255,nothing)

while True:

    R_l = cv2.getTrackbarPos('R_l', 'Mask')
    G_l = cv2.getTrackbarPos('G_l', 'Mask')
    B_l = cv2.getTrackbarPos('B_l', 'Mask')

    R_h = cv2.getTrackbarPos('R_h', 'Mask')
    G_h = cv2.getTrackbarPos('G_h', 'Mask')
    B_h = cv2.getTrackbarPos('B_h', 'Mask')

    _,frame = cap.read()
    blurred_frame = cv2.blur(frame,(5,5),0)

    hsv_frame = cv2.cvtColor(blurred_frame,cv2.COLOR_BGR2HSV)

    low_green = np.array([R_l, G_l, B_l])
    high_green = np.array([R_h, G_h, B_h])
    green_mask = cv2.inRange(hsv_frame, low_green, high_green)
    green = cv2.bitwise_and(frame, frame, mask=green_mask)

    contours,_ = cv2.findContours(green_mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)

    try:
        sorted_ = sorted(contours,key=cv2.contourArea,reverse=True)
        biggest = sorted_[0]
        cv2.drawContours(frame,biggest,-1,(255,0,0),1)
    except :
        pass
    #kernel = np.zeros(frame.shape(), np.uint8)
    x,y,w,h=cv2.boundingRect(biggest)
    roi= frame[y:y+h, x:x+w] 
    blurred_frame1 = cv2.blur(roi,(5,5),0)
    hsv_frame1 = cv2.cvtColor(blurred_frame1,cv2.COLOR_BGR2HSV)
    low_green1 = np.array([R_l, G_l, B_l])
    high_green1 = np.array([R_h, G_h, B_h])
    green_mask1 = cv2.inRange(hsv_frame1, low_green, high_green)
    green1= cv2.bitwise_and(roi,roi, mask=green_mask1)


    cv2.imshow("frame",frame)
    cv2.imshow("Mask",green1)
    key = cv2.waitKey(1)
    if key == 27:
        break
cap.release()
cv2.destroyAllWindows()

How can we prepare the desired image?我们如何准备所需的图像?

You're on the right track.你在正确的轨道上。 I suggest using HSV color thresholding with a lower/upper threshold to isolate the green leaves.我建议使用具有下限/上限阈值的 HSV 颜色阈值来隔离绿叶。 To determine the lower/upper HSV color threshold ranges, I used the HSV color thresholder script from a previous answer .为了确定 HSV 颜色阈值范围的下限/上限,我使用了上一个答案中的 HSV 颜色阈值脚本。 This will give us a binary mask.这将为我们提供一个二进制掩码。 From here we perform morphological operations to smooth the image and remove noise.从这里我们执行形态学操作来平滑图像并去除噪声。 Next we find contours and sort using contour area.接下来我们找到轮廓并使用轮廓区域进行排序。 We extract the largest contour, draw this onto a blank mask, then bitwise-and to get color.我们提取最大的轮廓,将其绘制到空白蒙版上,然后按位-并获得颜色。 From here we find the bounding rectangle coordinates on the mask then crop the ROI from the color image using Numpy slicing.从这里我们找到蒙版上的边界矩形坐标,然后使用 Numpy 切片从彩色图像中裁剪 ROI。 Here's the result这是结果

在此处输入图像描述

Code代码

import numpy as np
import cv2

# Read image, create blank masks, color threshold
image = cv2.imread('1.jpg')
blank_mask = np.zeros(image.shape, dtype=np.uint8)
original = image.copy()
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower = np.array([0, 18, 0])
upper = np.array([88, 255, 139])
mask = cv2.inRange(hsv, lower, upper)

# Perform morphological operations
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel, iterations=1)
close = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel, iterations=1)

# Find contours and filter for largest contour
# Draw largest contour onto a blank mask then bitwise-and
cnts = cv2.findContours(close, 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)[0]
cv2.fillPoly(blank_mask, [cnts], (255,255,255))
blank_mask = cv2.cvtColor(blank_mask, cv2.COLOR_BGR2GRAY)
result = cv2.bitwise_and(original,original,mask=blank_mask)

# Crop ROI from result
x,y,w,h = cv2.boundingRect(blank_mask)
ROI = result[y:y+h, x:x+w]

cv2.imshow('result', result)
cv2.imshow('ROI', ROI)
cv2.waitKey()

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

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