【问题标题】:Opencv and python for auto cropping用于自动裁剪的 Opencv 和 python
【发布时间】:2016-10-14 16:58:33
【问题描述】:

我想自动裁剪图像。

我为此使用 ImageMagick。

我正在使用的命令

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

我该如何解决这个问题。

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

【问题讨论】:

  • 在拍摄照片时可能需要更加注意使用对比背景——比如摄像师进行色度键控时...en.wikipedia.org/wiki/Chroma_key
  • @MarkSetchell 我就换个图吧,别管这个图了
  • @Piglet 这就是我要问的原因,如何解决它。因为我必须使用那种白色图像,我没有选择
  • 如果我在pixlr.com 上上传那个白色图像并且如果进行自动调整,那么我可以看到正确的图像。是否可以在图像魔术自动颜色或类似的东西中做
  • 请不要破坏您的帖子。请注意,一旦您在本网站上发布了问题或答案,这些帖子就会成为也为该内容做出贡献的其他人的集体努力的一部分。除非在特殊情况下,否则不应删除可能对其他人有用的帖子。即使该帖子对原作者不再有用,该信息仍然对将来可能遇到类似问题的其他人有益 - 这是 Stack Exchange 的基本理念。

标签: image image-processing imagemagick image-manipulation


【解决方案1】:

Kamyar Infinity 方法的问题是当某些背景颜色区域靠近对象时,您无法获得对象的正确边界。

设置为math.floor(numpy.average(imgray)) 的阈值对您没有帮助... 例如:

即使阈值是完美的(手动调整),你也不能忽视图像右上角的那个小点。您需要过滤掉一些区域。 例如:

opencv官方给出了实现方法。

Creating Bounding boxes and circles for contours

这里给出的另一种方法可能有用。 (与 Kamyar Infinity 基本相同,但添加了 cv.inRandge)

Dealing with contours and bounding rectangle in OpenCV 2.4 - python 2.7

【讨论】:

    【解决方案2】:

    如果你想用 OpenCV 做到这一点,一个好的起点可能是在做一些简单的处理以去除图像中的噪声和小细节之后,你可以找到图像的边缘,然后找到边界框并裁剪到那个区域。但是对于第二张图像,您可能需要进行一些后期处理,因为原始边缘可能会包含一些噪点和边界。您可以逐个像素地执行此操作,或者另一种可能过度杀伤的方法是找到图像中的所有轮廓并找到最大的边界框。使用它,您可以获得以下结果:

    第二个:

    需要工作的部分是找到适用于所有图像的适当阈值方法。在这里,我使用不同的阈值来制作二值图像,因为第一个大部分是白色的,而第二个则有点暗。第一个猜测是使用平均强度作为线索。

    希望这会有所帮助!

    编辑

    这就是我如何使用一些预处理和一个动态阈值来使其适用于两个图像:

    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数组内所有轮廓的边界框。

    这是第三张图片的结果:

    【讨论】:

    • 嗨,感谢您回答问题,我想知道 findContours 功能是否能够找到第二张图像的轮廓。如果是,那么该函数的参数是什么
    • @usernan 是的,它可以。我在答案中添加了我用来使其适用于两个图像的参数值。
    • 你说“检查轮廓区域以删除非常大的轮廓”,但我认为上面的代码会返回所有可能的轮廓,应该如何选择适合对象的单个轮廓
    • @usernan 我还添加了删除非常大的轮廓的代码。正如您在图像中看到的那样,没有与整个对象匹配的单个轮廓,因此您需要做的是遍历所有轮廓并找到所有轮廓中最小的 x 和最大的 y 以找到合适的边界框.
    • 感谢我刚刚修改了您的代码以获得我想要的。我仍然有一张图片会产生问题,请帮助解决这个问题,我会上传这些图片
    【解决方案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
    

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

    # 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
    

    【讨论】:

    • 嗨,它适用于白色图像,但不适用于我上传的第二张图片(新的蓝色一张)
    • 第二张图片底部有一小部分可能会造成问题
    猜你喜欢
    • 2020-03-28
    • 1970-01-01
    • 2023-03-05
    • 2015-06-17
    • 1970-01-01
    • 2020-09-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多