简体   繁体   English

如何在彩色边框内提取图像区域?

[英]How to extract area of an image within a colored border?

I am trying to extract the subsection area of an image based on the border of a colored box on the image (see below).我正在尝试根据图像上彩色框的边框提取图像的分段区域(见下文)。

I want to extract the area of the image within the yellow box.我想提取黄色框中的图像区域。 . .

For reference, I am extracting this image from a PDF using pdfplumber 's im.draw_rect function, which requires ImageMagick and Ghostscript.作为参考,我使用pdfplumberim.draw_rect function 从 PDF 中提取此图像,这需要 ImageMagick 和 Ghostscript。 I have looked everywhere I can for a solution to this problem, and while Mark Setchell's answer to the question Python: How to cut out an area with specific color from image (OpenCV, Numpy) has come close, I'm getting some unexpected errors.我到处寻找解决这个问题的方法,虽然 Mark Setchell 对问题Python: How to cut out a area with specific color from image (OpenCV, Numpy)的回答已经接近了,但我遇到了一些意想不到的错误.

Here is what I have tried so far:这是我到目前为止所尝试的:

import numpy as np
from PIL import Image, ImageFilter
impath = r'Path\to\drawn_p9_image.png'
im = Image.open(impath).convert('RGB')
na = np.array(im)
orig= na.copy()
im = im.filter(ImageFilter.MedianFilter(3))
yellowY, yellowX = np.where(np.all(na==[247,213,83],axis=2))
top, bottom = yellowY[0], yellowY[-1]

But when I run the last line, I get this error:但是当我运行最后一行时,我收到了这个错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: index 0 is out of bounds for axis 0 with size 0

So the NumPy array is not actually capturing the data it is supposed to.所以 NumPy 数组实际上并没有捕获它应该捕获的数据。 When I checked the NumPy array, this is what it output:当我检查 NumPy 数组时,这是 output:

>>> na
array([[[255, 255, 255],
        [255, 255, 255],
        [255, 255, 255],
        ...,
        [255, 255, 255],
        [255, 255, 255],
        [255, 255, 255]],

       [[255, 255, 255],
        [255, 255, 255],
        [255, 255, 255],
        ...,
        [255, 255, 255],
        [255, 255, 255],
        [255, 255, 255]],

       [[255, 255, 255],
        [255, 255, 255],
        [255, 255, 255],
        ...,
        [255, 255, 255],
        [255, 255, 255],
        [255, 255, 255]],

       ...,

       [[255, 255, 255],
        [255, 255, 255],
        [255, 255, 255],
        ...,
        [255, 255, 255],
        [255, 255, 255],
        [255, 255, 255]],

       [[255, 255, 255],
        [255, 255, 255],
        [255, 255, 255],
        ...,
        [255, 255, 255],
        [255, 255, 255],
        [255, 255, 255]],

       [[255, 255, 255],
        [255, 255, 255],
        [255, 255, 255],
        ...,
        [255, 255, 255],
        [255, 255, 255],
        [255, 255, 255]]], dtype=uint8)

I am not sure why this approach is not working, and am looking for some guidance on how to fix it.我不确定为什么这种方法不起作用,并且正在寻找有关如何解决它的一些指导。 I am fine with the yellow boundary being visible in the final cropped image, if that provides an easier solution.如果可以提供更简单的解决方案,我可以在最终裁剪的图像中看到黄色边界。

As Mark already pointed out in the comments, the yellow rectangle doesn't have the RGB value of [247, 213, 83] .正如马克在评论中已经指出的那样,黄色矩形没有[247, 213, 83]的 RGB 值。 ImageJ , for example, returns plain yellow [255, 255, 0] .例如, ImageJ返回纯黄色[255, 255, 0] So, using this value might already help.因此,使用此值可能已经有所帮助。

Nevertheless, to overcome those uncertainties regarding definitive RGB values, maybe also varying across platforms, software, and so on, I'd suggest to use color thresholding using the HSV color space , which also works using Pillow, cf.然而,为了克服关于确定 RGB 值的不确定性,可能还会因平台、软件等而变化,我建议使用HSV 颜色空间的颜色阈值,这也适用于 Pillow,参见。 modes . 模式

You only need to pay attention to the proper value ranges: The hue channel, for example, has values in the range of [0... 360] (degree), which are mapped to a full 8-bit, unsigned integer, ie to the range of [0... 255] .您只需要注意适当的取值范围:例如,色调通道的取值范围为[0... 360] (度),映射到完整的 8 位无符号 integer,即到[0... 255]的范围内。 Likewise, saturation and value are mapped from [0... 100] (percent) to [0... 255] .同样,饱和度和值从[0... 100] (百分比)映射到[0... 255]

The remainder is to find proper ranges for hue, saturation, and value (eg using some HSV color picker ), and NumPy's boolean array indexing to mask yellow-ish areas in the given image.剩下的就是找到合适的色调、饱和度和值范围(例如,使用一些HSV 颜色选择器),以及 NumPy 的boolean 数组索引以掩盖给定图像中的黄色区域。

For the final cropping, you could add some additional border to get rid of the yellow border itself.对于最终的裁剪,您可以添加一些额外的边框来摆脱黄色边框本身。

Finally, here's some code:最后,这里有一些代码:

import numpy as np
from PIL import Image


# Convert degree range (0 - 360) to uint8 value range (0 - 255)
def deg_to_uint8(deg):
    return deg / 360 * 255


# Convert percentage range (0 - 100) to uint8 value range (0 - 255)
def perc_to_uint8(perc):
    return perc / 100 * 255


# Open image, and convert to HSV color space for NumPy slicing
img = Image.open('MDRBG.png')
hsv = np.array(img.convert('HSV'))

# Masking color-ish area via NumPy slicing using upper and/or lower
# bounds for hue, saturation, and value
box = hsv[..., 0] > deg_to_uint8(55)        # Hue > 55°
box &= hsv[..., 0] < deg_to_uint8(65)       # Hue < 65°
box &= hsv[..., 1] > perc_to_uint8(80)      # Saturation > 80%
box &= hsv[..., 2] > perc_to_uint8(80)      # Value > 80%

# Find x, y coordinates of masked area; extract first and last elements
xy = np.argwhere(box)
t, b = xy[[0, -1], 0]
l, r = xy[[0, -1], 1]

# For better cropping, maybe add some additional border
bl, bt, br, bb = (3, 3, 3, 3)

# Actual cropping of the image
crop = img.crop((l + bl, t + bt, r - br, b - bb))
crop.save('crop.png')

And, that's the output:而且,这就是 output:

输出

----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.16299-SP0
Python:        3.9.1
NumPy:         1.20.2
Pillow:        8.1.2
----------------------------------------

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在绘图(Python)中选择区域并提取区域内的数据 - How to select area within a plot (Python) and extract the data within the area 如何获取图像中的边框像素或擦除区域 - How to get the border pixels or erased area in an image 如何使用 Python 提取图像中的绿色数字 - How can i extract numbers colored green in image using Python 如何在python中提取图像上的彩色区域并扭曲成所需的大小? - how to extract colored region on image and warp into desired size in python? 如何提取图像区域并将其重新插入原始图像? - How to extract an image area and plug it back in the original image? 从图像中提取轮廓区域 - Extract contour area from image 如何从这些彩色图像中提取文字? - How to extract text from these colored images? 如何在图像分割任务中填充掩码内的分割区域? - How to fill segmented area within a mask in image segmentation task? 使用python,如何计算图像中具有指定尺寸的对象区域 - Using python, how to count area of objects with specified dimensions within an image 识别图像的红色部分并仅提取它们的强度 - Python - Identify red colored parts of an image and extract only their intensity - Python
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM