根据值

时间:2016-01-27 13:33:48

标签: python numpy image-processing crop bounding-box

我有多张图片,看起来像这样:enter image description here

橙色表示等于0的值,白色表示等于255的值,蓝色表示字段,其中值从0到255变化。我想摆脱橙色区域,这是每张图片略有不同。最好的方法是什么?

编辑1

我认为这个答案可能有所帮助:bounding box approach。 除此之外,我想获得一个数组A_extract而不是A_trim

A = np.array([[0,   0,   0,   0,   0,   0, 0],
              [0, 255,   0,   0,   0,   0, 0],
              [0,   0, 255, 255, 255, 255, 0],
              [0,   0, 255,   0, 255,   0, 0],
              [0,   0, 255, 255, 255,   0, 0],
              [0,   0,   0, 255,   0,   0, 0],
              [0,   0,   0,   0,   0,   0, 0]])

A_trim = np.array([[255,   0,   0,   0,   0],
                   [  0, 255, 255, 255, 255],
                   [  0, 255,   0, 255,   0],
                   [  0, 255, 255, 255,   0],
                   [  0,   0, 255,   0,   0]])

A_extract = np.array([[255, 255, 255],
                      [255,   0, 255],
                      [255, 255, 255])

基本上,代码应该找到一个边界框,其中第一行和最后一行(以及第一列和最后一列)中的所有元素应该具有相同的值(例如255)。

编辑2

真实图像是分类的卫星图像,存储为numpy数组(形状为cca.7000x8000)而不是RGB图像。这就是它的样子:

  • orange = 0
  • green = 2
  • pink = 3
  • white = 255

目标是在边缘摆脱0值。

enter image description here

3 个答案:

答案 0 :(得分:0)

采用新方法编辑:

  

基本上,代码应该找到一个边界框,其中第一行和最后一行(以及第一列和最后一列)中的所有元素应该具有相同的值(例如255)。

这种方法有帮助,但在样本图像上效果不佳。所以,我在此基础上添加了额外的检查。速度可能是一个问题,因为只使用PIL,真实的图像是巨大的。希望有人能想出一个笨拙的解决方案。

以下代码中只需要两个变量:

1)。背景颜色:样本图像是(250,255,255)(不是255,255,255?);

2)。保证金范围:代码使用范围(2,30)。它会影响处理时间,因为枚举了所有可能的值。

from PIL import Image

BG_COLOR = (250, 255, 255) # background color
MARGIN = range(2, 30) # Define your margin range
tuple_list = [] # hold the tuple list result

if __name__ == '__main__':
    im = Image.open('dEGdp.png').convert('RGB')    
    w,h = im.size
    pix = im.load()
    for x1 in MARGIN:
        for y1 in MARGIN:
            for x2 in MARGIN:
                for y2 in MARGIN:
                    if pix[x1,y1] == pix[w-x2,y1] == pix[x1, h-y2]== pix[w-x2,h-y2] == BG_COLOR and \
                        (any([pix[x1-1,y]!= BG_COLOR or pix[w-x2+1, y] != BG_COLOR for y in range(0, h)]) or \
                         any([pix[x, y1] != BG_COLOR or pix[x, h-y2+1] != BG_COLOR for x in range(0, w)])):
                        tuple_list.append(((w-x1-x2)*(h-y1-y2), x1, y1, w-x2, h-y2))
                    else: continue
    top_box = sorted(tuple_list).pop() #pick the top one
    im_c = im.crop((top_box[1:])) # crop the image
    im_c.save('cropped.png')

输出效果很好: enter image description here

答案 1 :(得分:0)

啊哈!现在我可以看到你的形象,我可以帮助更好。同样,我将使用 ImageMagick 描述一种方法,但您可以轻松地将其应用于OpenCV / Python。

首先,你的图像是一个分类的图像,它是PNG,这意味着它是非常好的 - 只有8种颜色,没有量化文物 - 最后!关于时间有人使用正确的格式进行图像处理任务: - )

第一项工作是找到"讨厌的边缘像素" 的颜色。一个简单的方法,允许颜色变化,是从角落采取100x100块 - 确保找到一些"讨厌的像素" 。然后使白色透明并找到剩余可见像素的颜色。这是 ImageMagick 中的一行:

convert satellite.png -fuzz 10% -crop 100x100+0+0 -transparent white result.png

enter image description here

这显示了上下文中的裁剪区域:

enter image description here

然后我们需要这张图片的平均颜色 - 这是"讨厌的像素" 的颜色,因为白色是透明的:

convert satellite.png -fuzz 10% -crop 100x100+0+0 -transparent white -resize 1x1 txt:
# ImageMagick pixel enumeration: 1,1,255,srgba
0,0: (61937,45232,11308,4857)  #F1B02C13  srgba(241,176,44,0.0741131)

所以,橙色​​是srgba(241,176,44,0.0741131)

现在,我们在小裁剪区域找到一个像素作为填充洪水的种子:

# ImageMagick pixel enumeration: 100,100,255,srgba
0,0: (65535,65535,65535,0)  #FFFFFF00  srgba(255,255,255,0)
1,0: (65535,65535,65535,0)  #FFFFFF00  srgba(255,255,255,0)
2,0: (65535,65535,65535,0)  #FFFFFF00  srgba(255,255,255,0)
...
97,7: (65535,65535,65535,0)  #FFFFFF00  srgba(255,255,255,0)
98,7: (65535,65535,65535,0)  #FFFFFF00  srgba(255,255,255,0)
99,7: (65535,65535,65535,0)  #FFFFFF00  srgba(255,255,255,0)
0,8: (65535,65535,65535,0)  #FFFFFF00  srgba(255,255,255,0)
1,8: (65535,65535,65535,0)  #FFFFFF00  srgba(255,255,255,0)
2,8: (65535,65535,65535,0)  #FFFFFF00  srgba(255,255,255,0)
3,8: (65535,65535,65535,0)  #FFFFFF00  srgba(255,255,255,0)
4,8: (65535,65535,65535,0)  #FFFFFF00  srgba(255,255,255,0)
5,8: (65535,65535,65535,0)  #FFFFFF00  srgba(255,255,255,0)
6,8: (65535,65535,65535,0)  #FFFFFF00  srgba(255,255,255,0)
7,8: (61937,45232,11308,65535)  #F1B02CFF  srgba(241,176,44,1)   <--- FIRST PESKY PIXEL
8,8: (61937,45232,11308,65535)  #F1B02CFF  srgba(241,176,44,1)
9,8: (61937,45232,11308,65535)  #F1B02CFF  srgba(241,176,44,1)
10,8: (61937,45232,11308,65535)  #F1B02CFF  srgba(241,176,44,1)
11,8: (61937,45232,11308,65535)  #F1B02CFF  srgba(241,176,44,1)
12,8: (61937,45232,11308,65535)  #F1B02CFF  srgba(241,176,44,1)
13,8: (61937,45232,11308,65535)  #F1B02CFF  srgba(241,176,44,1)
14,8: (61937,45232,11308,65535)  #F1B02CFF  srgba(241,176,44,1)

所以,srgba(241,176,44,0.0741131)任何人都会这样做,让我们选择第一个像素[7,8]

现在我们可以从那里开始填充图像:

convert satellite.png -fill white -floodfill +7+8 "#F1B02CFF" result.png

enter image description here

你可以看到它充满了&#34;讨厌的像素&#34; 的左栏。现在在其他三个角中找到一个类似的种子像素并重复。

答案 2 :(得分:0)

张贴的图像有一个白色边框,然后在你到达橙色之前三面有一些黑线。

这将删除白色边框,然后变为橙色到白色:

 convert amGCH.png -trim -fill white -draw "color 5,5 floodfill" output.png