使用OpenCV和Python进行自动裁剪

5

我希望能自动裁剪图片。

我正在使用ImageMagick进行操作。

我使用的命令是

 convert  3.jpg  -fuzz 10%  -trim     trim.jpg

这里输入图片描述

这里输入图片描述

如何解决这个问题。

我认为设置的模糊因子有问题。


当你拍摄照片时,可能需要更加注意使用对比鲜明的背景 - 就像视频制作人进行色度键控一样...https://en.wikipedia.org/wiki/Chroma_key - Mark Setchell
如果我在 https://pixlr.com/ 上上传那个白色图片,并进行自动调整,那么我可以看到正确的图像。在 ImageMagick 中是否有类似的自动颜色功能? - usernan
请勿破坏您的帖子。请注意,一旦您在此网站上发布问题或答案,这些帖子将成为其他人共同努力的一部分,他们也为该内容做出了贡献。对于可能对他人有用的帖子,除非情况特殊,否则不应删除。即使该帖子对原作者已经不再有用,该信息仍然对未来可能遇到类似问题的其他人有益 - 这是 Stack Exchange 的基本理念。 - Matt
@Matt 我把这个问题搞砸了。 - usernan
@usernan:那就发一个新问题吧。删除此问题并不是发布新问题的先决条件。 - Matt
显示剩余2条评论
3个回答

14
如果您想使用OpenCV实现此操作,一个好的起点是在对图像进行简单处理以消除噪声和小细节后,找到图像的边缘,然后找到边界框并将其裁剪到该区域。但是,在第二张图片的情况下,您可能需要进行一些后处理,因为原始边缘可能会包含一些噪音和边框。您可以基于像素逐个处理,或者另一种可能过度处理的方法是查找图像中的所有轮廓,然后找到最大的边界框。使用这种方法,您可以获得以下结果:First Image 至于第二个图像:

Second Image

需要改进的部分是找到适用于所有图像的合适阈值方法。在这里,我使用了不同的阈值来制作二元图像,因为第一个阈值大多是白色的,而第二个阈值则稍微暗一些。第一个猜测是使用平均强度作为线索。希望这有所帮助!
编辑
这是我如何使用一些预处理和动态阈值来使它适用于这两张图片的方式:
im = cv2.imread('cloth.jpg')
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
imgray = cv2.blur(imgray,(15,15))
ret,thresh = cv2.threshold(imgray,math.floor(numpy.average(imgray)),255,cv2.THRESH_BINARY_INV)
dilated=cv2.morphologyEx(thresh, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(10,10)))
_,contours,_ = cv2.findContours(dilated,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)

我还检查了轮廓面积,以删除非常大的轮廓:

new_contours=[]
for c in contours:
    if cv2.contourArea(c)<4000000:
        new_contours.append(c)

数字4000000是图像大小(宽度*高度)的估计值,大的轮廓应该有接近图像大小的面积。

然后您可以迭代所有轮廓,并找到整个边界框:

best_box=[-1,-1,-1,-1]
for c in new_contours:
   x,y,w,h = cv2.boundingRect(c)
   if best_box[0] < 0:
       best_box=[x,y,x+w,y+h]
   else:
       if x<best_box[0]:
           best_box[0]=x
       if y<best_box[1]:
           best_box[1]=y
       if x+w>best_box[2]:
           best_box[2]=x+w
       if y+h>best_box[3]:
           best_box[3]=y+h

你现在拥有 best_box 数组内所有轮廓的边界框。
以下是第三张图片的结果: Third Image

@usernan 你需要保留所有的轮廓,并处理它们以获取所需的边界框。请查看我的新编辑。 - Kamyar Infinity
想知道如何处理带有阴影的图像,因为某些图像会出现问题。 - usernan
如果衣服本身颜色较暗,很难分辨,因为阴影看起来像是衣服的一部分。但对于其他情况,您可以将其转换到HSV颜色空间,并选择Value通道中值较低的区域来找到暗区域。 - Kamyar Infinity
我已经使用了自适应阈值(adaptiveThreshold)来处理图像,可以在我的第四个编辑上传的图像中看到效果。但是如果我想在这个图像上找到轮廓(contour),我无法得到正确的结果。 - usernan
我不确定adaptiveThreshold,因为它没有太多的选项。你使用了ADAPTIVE_THRESH_MEAN_C模式吗?这个模式应该在最终图像中提供更多的细节。 - Kamyar Infinity
显示剩余10条评论

3
你可以尝试分离饱和度通道,并按预期进行裁剪。
# Convert to HSV, isolate saturation channel, and switch to format
# that supports extended paging.
convert source.jpg -colorspace HSV -channel S -separate /tmp/saturation.png

saturation channel

# Trim as before
convert /tmp/saturation.png -trim /tmp/trim.png

trim

# Capture results of -trim
GEO=$(identify -format '%wx%h%X%Y' /tmp/trim.png)

1232x1991+384+336

# Apply results to original image
convert source.jpg -crop $GEO trim.jpg

finish


嗨,它可以用于白色图像,但不能用于我上传的第二张图像(新的蓝色图像)。 - usernan
第二张图片底部可能有一个小问题。 - usernan

2
Kamyar Infinity方法的问题在于,当某个背景颜色区域接近物体时,您无法得到正确的物体边界。
阈值设置为math.floor(numpy.average(imgray))也无法帮助您...例如:

enter image description here

尽管阈值调整得很完美(手动调整),但您不能忽略图像右上角的那个小点。您需要过滤掉一些区域。例如:

enter image description here

这个方法是由opencv官方提供的。 创建轮廓的边界框和圆形
这里还提供了另一种方法,可能会有用(基本上与Kamyar Infinity相同,但添加了cv.inRange)。 在OpenCV 2.4中处理轮廓和边界矩形 - Python 2.7

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接