【问题标题】:How to auto crop the white part of this picture that is inside the grey?如何自动裁剪这张图片中灰色内的白色部分?
【发布时间】:2019-10-09 08:39:45
【问题描述】:

我想裁剪掉灰色中的白色部分,并将其保存为数千张图片的新图片。这可以通过 PIL 或 opencv 来完成吗?如果有怎么办? 图片可以是这样的:

我知道 PIL 库有 n 个裁剪,但是如何让脚本自动找到灰色中的白色部分?白色部分有时包含其他图像,有时也包含文本。所以白色部分并不总是像示例中那样是空白的白色或只有黑色的框架。

【问题讨论】:

  • 您可以添加预期的输出图像吗?
  • 查看帖子中的链接。 stackoverflow 还不允许我发布图片..

标签: python opencv python-imaging-library


【解决方案1】:

如果您愿意使用 ImageMagick,这可以在一行代码中使用它的 -trim 函数完成两次,对于两个灰色区域(暗区和亮区)各一次。修剪功能在背景中寻找几乎恒定的区域并将其移除。 -fuzz XX% 是每个区域中灰色颜色的百分比变化,被认为是相同的颜色。

Imagemagick 已经安装在大多数 Linux 发行版中,它也可用于 Windows 和 Mac OSX。

输入:

convert 0.png -fuzz 30% -trim +repage -trim +repage 0_trim.png


事实上,您可以使用 ImageMagick mogrify 而不是转换来处理整个文件夹的图像。

Create a new directory to hold the output
Change directory to the one containing your images
mogrify -path path_to/new_directory -fuzz 30% -trim +repage -trim +repage *


您还可以使用基于 ImageMagick 的 Python Wand。请参阅http://docs.wand-py.org/en/latest/wand/image.html 的修剪。这是魔杖代码:

#!/bin/python3.7

from wand.image import Image

with Image(filename='0.png') as img:
    img.trim(fuzz=0.3*img.quantum_range)
    img.save(filename='0_wand_trim.png')


如果您想这样做,也可以从 Python 对 ImageMagick 进行子进程调用。

#!/opt/local/bin/python3.7

import subprocess

cmd = 'convert 0.png -fuzz 30% -trim +repage -trim +repage 0_trim.png'
subprocess.check_output(cmd, shell=True, universal_newlines=True)


您可能需要提供要转换的路径,如果它不在您的 PATH 环境变量中。

【讨论】:

    【解决方案2】:

    这里是主要思想:

    • 将图像转换为灰度和模糊图像
    • 执行精确边缘检测
    • 查找图像的轮廓并查找每个轮廓的区域
    • 过滤最大轮廓区域并裁剪 ROI 部分

    Canny 边缘检测

    现在我们遍历每个轮廓并过滤以绿色突出显示的最大轮廓。

    从边界框坐标裁剪 ROI

    import numpy as np
    import cv2
    
    original_image = cv2.imread("1.png")
    image = original_image.copy()
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (3, 3), 0)
    canny = cv2.Canny(blurred, 120, 255, 1)
    
    # Find contours in the image
    cnts = cv2.findContours(canny.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    
    # Obtain area for each contour
    contour_sizes = [(cv2.contourArea(contour), contour) for contour in cnts]
    
    # Find maximum contour and crop for ROI section
    if len(contour_sizes) > 0:
        largest_contour = max(contour_sizes, key=lambda x: x[0])[1]
        x,y,w,h = cv2.boundingRect(largest_contour)
        cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 2)
        ROI = original_image[y:y+h, x:x+w]
        cv2.imshow("ROI", ROI) 
    
    cv2.imshow("canny", canny) 
    cv2.imshow("detected", image) 
    cv2.waitKey(0)
    

    【讨论】:

    • 您可以通过在findContours 中使用cv2.RETR_EXTERNAL 而不是cv2.RETR_TREE 来提高性能。它只返回最外面的轮廓,所以你不会找到最大的,你可以选择找到的那个。
    • 我最初使用cv2.RETR_EXTERNAL,但它返回图像的外部窗口而不是外部白色部分
    • 第二次检查时,cv2.RETR_EXTERNAL 有效。我想我最初在原始图像上尝试过,没有进行模糊或预处理。
    • canny.copy() 不用复制图片了。
    猜你喜欢
    • 2021-05-23
    • 2012-05-27
    • 2020-08-15
    • 2017-10-17
    • 1970-01-01
    • 1970-01-01
    • 2018-05-04
    • 1970-01-01
    • 2015-06-15
    相关资源
    最近更新 更多