3

私はページセグメンテーションアルゴリズムを使用しています。コードの出力は、各ゾーンのピクセルに一意の色が割り当てられた画像を書き込みます。画像を処理して、ゾーンの境界ボックスを見つけたいと思います。すべての色を見つけ、次にその色のすべてのピクセルを見つけ、次にそれらのバウンディングボックスを見つける必要があります。

以下は画像の例です。

色付きのゾーンを示す出力画像の例

私は現在、R、G、Bチャネルのヒストグラムから始めています。ヒストグラムはデータの場所を教えてくれます。

img = Image.open(imgfilename)
img.load()
r,g,b = img.split()

ra,ga,ba = [ np.asarray(p,dtype="uint8") for p in (r,g,b) ]

rhist,edges = np.histogram(ra,bins=256)
ghist,edges = np.histogram(ga,bins=256)
bhist,edges = np.histogram(ba,bins=256)
print np.nonzero(rhist)
print np.nonzero(ghist)
print np.nonzero(bhist)

出力:(array([0、1、128、205、255])、)(array([0、20、128、186、255])、)(array([0、128、147、150、255] )、)

私はこの時点で少し混乱しています。目視で見ると、色(0,0,0)、(1,0,0)、(0,20,0)、(128,128,128)などがあります。ゼロ以外の出力をnp.where()のピクセル値に並べ替えるにはどうすればよいですか?

3、row、col narrayを24ビットパックRGB値(r << 24 | g << 16 | b)の2次元平面に平坦化し、その配列を検索することを検討しています。それはブルートフォースでエレガントではないようです。Numpyでカラー値のバウンディングボックスを見つけるためのより良い方法はありますか?

4

3 に答える 3

4

これをRGBカラー画像と見なす理由はありません。他の誰かが行ったセグメンテーションの視覚化にすぎません。グレースケール画像と簡単に見なすことができ、これらの特定の色については、他に何もする必要はありません。

import sys
import numpy
from PIL import Image

img = Image.open(sys.argv[1]).convert('L')

im = numpy.array(img) 
colors = set(numpy.unique(im))
colors.remove(255)

for color in colors:
    py, px = numpy.where(im == color)
    print(px.min(), py.min(), px.max(), py.max())

固有の色を与えることに頼ることができない場合convert('L')(つまり、指定された画像の色以外の色を使用している場合)、画像をパックして固有の色を取得できます。

...
im = numpy.array(img, dtype=int)

packed = im[:,:,0]<<16 | im[:,:,1]<<8 | im[:,:,2]
colors = set(numpy.unique(packed.ravel()))
colors.remove(255<<16 | 255<<8 | 255)

for color in colors:
    py, px = numpy.where(packed == color)
    print(px.min(), py.min(), px.max(), py.max())

ちなみに、バウンディングボックスを見つける前に、接続されている小さなコンポーネントを削除することもお勧めします。

于 2013-01-26T16:53:01.160 に答える
2

編集投稿した画像を使用して、すべてを作業プログラムにまとめます。

from __future__ import division
import numpy as np
import itertools
from PIL import Image

img = np.array(Image.open('test_img.png'))

def bounding_boxes(img) :
    r, g, b = [np.unique(img[..., j]) for j in (0, 1, 2)]
    bounding_boxes = {}
    for r0, g0, b0 in itertools.product(r, g, b) :
        rows, cols = np.where((img[..., 0] == r0) &
                              (img[..., 1] == g0) &
                              (img[..., 2] == b0))
        if len(rows) :
            bounding_boxes[(r0, g0, b0)] = (np.min(rows), np.max(rows),
                                            np.min(cols), np.max(cols))
    return bounding_boxes

In [2]: %timeit bounding_boxes(img)
1 loops, best of 3: 30.3 s per loop

In [3]: bounding_boxes(img)
Out[3]: 
{(0, 0, 255): (3011, 3176, 755, 2546),
 (0, 128, 0): (10, 2612, 0, 561),
 (0, 128, 128): (1929, 1972, 985, 1438),
 (0, 255, 0): (10, 166, 562, 868),
 (0, 255, 255): (2938, 2938, 680, 682),
 (1, 0, 0): (10, 357, 987, 2591),
 (128, 0, 128): (417, 1873, 984, 2496),
 (205, 186, 150): (11, 56, 869, 1752),
 (255, 0, 0): (3214, 3223, 570, 583),
 (255, 20, 147): (2020, 2615, 956, 2371),
 (255, 255, 0): (3007, 3013, 600, 752),
 (255, 255, 255): (0, 3299, 0, 2591)}

実際にチェックされる色の数が少なくても、それほど高速ではありません...


r0色、g0b0の線に沿った何かの境界ボックスを見つけることができます

rows, cols = np.where((ra == r0) & (ga == g0) & (ba == b0))
top, bottom = np.min(rows), np.max(rows)
left, right = np.min(cols), np.max(cols)

RGB カラーのすべての組み合わせを繰り返すのではなく2**24、ゼロ以外のヒストグラム ビンのデカルト積のみを使用して検索スペースを大幅に削減できます。

for r0, g0, b0 in itertools.product(np.nonzero(rhist),
                                    np.nonzero(ghist),
                                    np.nonzero(bhist)) :

存在しない組み合わせが漏れ、それをチェックして除外でき、空のタプルではありませんrowscolsしかし、あなたの例では、2**24組み合わせの検索スペースをわずか 125 に減らします。

于 2013-01-26T15:43:09.290 に答える
0

これは私の頭から離れた解決策にすぎません。画像のピクセルを左上から右下まで繰り返し、各色の、、、および値をtop保存できます。特定の色について、値はこの色で表示される最初の行になり、最後のrawになります。値はこの色のピクセルの最小列値になり、は最大列値になります。bottomleftrighttopbottomleftright

次に、各色について、希望の色でからtop-leftまでの長方形を描くことができます。bottom-right

これが適切なバウンディングボックスアルゴリズムとして適格かどうかはわかりませんが、問題ないと思います。

于 2013-01-26T15:24:01.077 に答える