为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

隔江千里 2021-10-12 15:45:14
我正在尝试用绿色背景剪切多个图像。图片的中心是绿色的,我想剪掉图片中的其余部分。问题是,我从视频中获取图片,所以有时绿色中心更大,有时更小。我的真正任务是在结上使用 K-Means,因此我有例如绿色背景和两条绳索,一根蓝色一根红色。我将 python 与 opencv、numpy 和 matplotlib 一起使用。我已经剪掉了中心,但有时我剪得太多,有时我剪得太少。在此示例中,我的图像大小为 1920 x 1080。到目前为止,这是我的代码:import numpy as npimport cv2import matplotlib.pyplot as pltfrom PIL import Image, ImageEnhanceimg = 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()
查看完整描述

3 回答

?
Smart猫小萌

TA贡献1911条经验 获得超7个赞

下面的代码做你想要的。首先,它将图像转换为 HSV 色彩空间,这使得选择颜色更加容易。接下来制作一个仅选择绿色部分的蒙版。去除了一些噪音并汇总了行和列。最后,基于绿色选择中的第一行/最后一行/列创建一个新图像。

由于在所有提供的示例中需要裁剪掉一些额外的顶部,因此我添加了代码来做到这一点。首先,我倒置了面具。现在您可以使用行/列的总和来查找完全在绿色选择范围内的行/列。它是为顶部完成的。在窗口下方的图像中,“Roi2”是最终图像。

编辑:ts 评论后更新代码。
更新结果:

//img1.sycdn.imooc.com//61653d3d0001a8e205050475.jpg

代码:


import numpy as np 

import cv2


# load image

img = cv2.imread("gr.png")

# convert to HSV

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) 

# set lower and upper color limits

lower_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 green

mask = cv2.inRange(hsv, lower_val, upper_val)

# remove noise

kernel =  np.ones((8,8),np.uint8)

mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)


# sum each row and each volumn of the image

sumOfCols = 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 variables

for i in range(len(sumOfCols)):

    if sumOfCols[i] > 0:

        x1 = i

        print('First col: ' + str(i))

        break


for i in range(len(sumOfCols)-1,-1,-1):

    if sumOfCols[i] > 0:

        x2 = i

        print('Last col: ' + str(i))

        break


for i in range(len(sumOfRows)):

    if sumOfRows[i] > 0:

        y1 = i

        print('First row: ' + str(i))

        break


for 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 white

mask_inv = cv2.bitwise_not(mask)

# search the first and last column top down for a green pixel and cut off at lowest common point

for 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 values

roi2 = img[y1:y2,x1:x2]


cv2.imshow("Roi2", roi2)

cv2.imwrite("img_cropped.jpg", roi2)

cv2.waitKey(0)

cv2.destroyAllWindows()



查看完整回答
反对 回复 2021-10-12
?
12345678_0001

TA贡献1802条经验 获得超5个赞

根据您添加的新图像,我假设您不仅希望按照要求剪掉非绿色部分,而且还希望绳索/结周围有一个较小的框架。那是对的吗?如果没有,您应该上传视频并更多地描述裁剪的目的/目标,以便我们更好地为您提供帮助。

假设你想要一个只有绳索的裁剪图像,解决方案与之前的答案非常相似。但是,这次绳索的红色和蓝色是使用 HSV 选择的。根据生成的蒙版裁剪图像。如果您希望图像比绳索大一些,您可以添加额外的边距 - 但一定要考虑/检查图像的边缘。

注意:下面的代码适用于具有全绿色背景的图像,因此我建议您将其与仅选择绿色区域的解决方案之一结合使用。我对您的所有图像进行了如下测试:我从我的另一个答案中获取了代码,将其放入一个函数中并添加return roi2到最后。此输出被馈送到保存以下代码的第二个函数。所有图像处理成功。

结果:

//img1.sycdn.imooc.com//61653d55000184d905380610.jpg

代码:


import numpy as np 

import cv2


# load image

img = cv2.imread("image.JPG")

# blue

lower_val_blue = (110, 0, 0)

upper_val_blue = (179,255,155)

# red

lower_val_red = (0, 0, 150)

upper_val_red = (10,255,255)

# Threshold the HSV image

mask_blue = cv2.inRange(img, lower_val_blue, upper_val_blue)

mask_red = cv2.inRange(img, lower_val_red, upper_val_red)

# combine masks

mask_total = cv2.bitwise_or(mask_blue,mask_red)


# remove noise

kernel =  np.ones((8,8),np.uint8)

mask_total = cv2.morphologyEx(mask_total, cv2.MORPH_CLOSE, kernel)


# sum each row and each volumn of the mask

sumOfCols = 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 variables

for i in range(len(sumOfCols)):

    if sumOfCols[i] > 0:

        x1 = i

        print('First col: ' + str(i))

        break


for i in range(len(sumOfCols)-1,-1,-1):

    if sumOfCols[i] > 0:

        x2 = i

        print('Last col: ' + str(i))

        break


for i in range(len(sumOfRows)):

    if sumOfRows[i] > 0:

        y1 = i

        print('First row: ' + str(i))

        break


for 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 image

cv2.imshow("Result", roi)

cv2.imshow("Image", img)


cv2.waitKey(0)

cv2.destroyAllWindows()



查看完整回答
反对 回复 2021-10-12
  • 3 回答
  • 0 关注
  • 239 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信