如何从 Python 中的其余图片中剪切带有前景的绿色背景?

我正在尝试用绿色背景剪切多个图像。图片的中心是绿色的,我想剪掉图片中的其余部分。问题是,我从视频中获取图片,所以有时绿色中心更大,有时更小。我的真正任务是在结上使用 K-Means,因此我有例如绿色背景和两条绳索,一根蓝色一根红色。

我将 python 与 opencv、numpy 和 matplotlib 一起使用。

我已经剪掉了中心,但有时我剪得太多,有时我剪得太少。在此示例中,我的图像大小为 1920 x 1080。

到目前为止,这是我的代码:


import numpy as np

import cv2

import matplotlib.pyplot as plt

from PIL import Image, ImageEnhance


img = cv2.imread('path')


print(img.shape)


imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)


crop_img = imgRGB[500:500+700, 300:300+500]


plt.imshow(crop_img)

plt.show()


隔江千里
浏览 240回答 3
3回答

Smart猫小萌

下面的代码做你想要的。首先,它将图像转换为 HSV 色彩空间,这使得选择颜色更加容易。接下来制作一个仅选择绿色部分的蒙版。去除了一些噪音并汇总了行和列。最后,基于绿色选择中的第一行/最后一行/列创建一个新图像。由于在所有提供的示例中需要裁剪掉一些额外的顶部,因此我添加了代码来做到这一点。首先,我倒置了面具。现在您可以使用行/列的总和来查找完全在绿色选择范围内的行/列。它是为顶部完成的。在窗口下方的图像中,“Roi2”是最终图像。编辑:ts 评论后更新代码。更新结果:代码:import numpy as np import cv2# load imageimg = cv2.imread("gr.png")# convert to HSVhsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # set lower and upper color limitslower_val = (30, 0, 0)upper_val = (65,255,255)# Threshold the HSV image to get only green colors# the mask has white where the original image has greenmask = cv2.inRange(hsv, lower_val, upper_val)# remove noisekernel =  np.ones((8,8),np.uint8)mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)# sum each row and each volumn of the imagesumOfCols = np.sum(mask, axis=0)sumOfRows = np.sum(mask, axis=1)# Find the first and last row / column that has a sum value greater than zero, # which means its not all black. Store the found values in variablesfor i in range(len(sumOfCols)):    if sumOfCols[i] > 0:        x1 = i        print('First col: ' + str(i))        breakfor i in range(len(sumOfCols)-1,-1,-1):    if sumOfCols[i] > 0:        x2 = i        print('Last col: ' + str(i))        breakfor i in range(len(sumOfRows)):    if sumOfRows[i] > 0:        y1 = i        print('First row: ' + str(i))        breakfor i in range(len(sumOfRows)-1,-1,-1):    if sumOfRows[i] > 0:        y2 = i        print('Last row: ' + str(i))        break# create a new image based on the found values#roi = img[y1:y2,x1:x2]#show images#cv2.imshow("Roi", roi)# optional: to cut off the extra part at the top:#invert mask, all area's not green become whitemask_inv = cv2.bitwise_not(mask)# search the first and last column top down for a green pixel and cut off at lowest common pointfor i in range(mask_inv.shape[0]):    if mask_inv[i,0] == 0 and mask_inv[i,x2] == 0:        y1 = i        print('First row: ' + str(i))        break# create a new image based on the found valuesroi2 = img[y1:y2,x1:x2]cv2.imshow("Roi2", roi2)cv2.imwrite("img_cropped.jpg", roi2)cv2.waitKey(0)cv2.destroyAllWindows()

12345678_0001

根据您添加的新图像,我假设您不仅希望按照要求剪掉非绿色部分,而且还希望绳索/结周围有一个较小的框架。那是对的吗?如果没有,您应该上传视频并更多地描述裁剪的目的/目标,以便我们更好地为您提供帮助。假设你想要一个只有绳索的裁剪图像,解决方案与之前的答案非常相似。但是,这次绳索的红色和蓝色是使用 HSV 选择的。根据生成的蒙版裁剪图像。如果您希望图像比绳索大一些,您可以添加额外的边距 - 但一定要考虑/检查图像的边缘。注意:下面的代码适用于具有全绿色背景的图像,因此我建议您将其与仅选择绿色区域的解决方案之一结合使用。我对您的所有图像进行了如下测试:我从我的另一个答案中获取了代码,将其放入一个函数中并添加return roi2到最后。此输出被馈送到保存以下代码的第二个函数。所有图像处理成功。结果:代码:import numpy as np import cv2# load imageimg = cv2.imread("image.JPG")# bluelower_val_blue = (110, 0, 0)upper_val_blue = (179,255,155)# redlower_val_red = (0, 0, 150)upper_val_red = (10,255,255)# Threshold the HSV imagemask_blue = cv2.inRange(img, lower_val_blue, upper_val_blue)mask_red = cv2.inRange(img, lower_val_red, upper_val_red)# combine masksmask_total = cv2.bitwise_or(mask_blue,mask_red)# remove noisekernel =  np.ones((8,8),np.uint8)mask_total = cv2.morphologyEx(mask_total, cv2.MORPH_CLOSE, kernel)# sum each row and each volumn of the masksumOfCols = np.sum(mask_total, axis=0)sumOfRows = np.sum(mask_total, axis=1)# Find the first and last row / column that has a sum value greater than zero, # which means its not all black. Store the found values in variablesfor i in range(len(sumOfCols)):    if sumOfCols[i] > 0:        x1 = i        print('First col: ' + str(i))        breakfor i in range(len(sumOfCols)-1,-1,-1):    if sumOfCols[i] > 0:        x2 = i        print('Last col: ' + str(i))        breakfor i in range(len(sumOfRows)):    if sumOfRows[i] > 0:        y1 = i        print('First row: ' + str(i))        breakfor i in range(len(sumOfRows)-1,-1,-1):    if sumOfRows[i] > 0:        y2 = i        print('Last row: ' + str(i))        break# create a new image based on the found valuesroi = img[y1:y2,x1:x2]#show imagecv2.imshow("Result", roi)cv2.imshow("Image", img)cv2.waitKey(0)cv2.destroyAllWindows()
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python