2017-04-13 6 views
3

12色のRGB画像がありますが、色(ピクセル値)はあらかじめわかりません。私は0と11の間のすべてのピクセル値を変換したい、それぞれ元のrgbイメージのユニークな色を象徴する。画像のすべてのピクセル値を特定の範囲に変換する方法-python

すべての[230,100,140]は[0,0,0]に変換され、[130,90,100]は[0,0,1]に変換されます...すべて[210,80,50]は[0,0、 11]。

+0

ですから、最初の色のセットを構築して、インデックスにそれらをマッピングしますか? –

+0

@Miki:これはピクセルにインデックスを割り当てません。ここでは12色を選択します。しかし、イメージには12色しか含まれていません。 –

+0

ある範囲を別の範囲に変換する必要があります。このリンクをチェックしてください:https://stackoverflow.com/questions/929103/convert-a-number-range-to-another-range-maintaining-ratio – zindarod

答えて

1

クイックアンドダーティーアプリケーション。

import cv2 
import numpy as np 

#finding unique rows 
#comes from this answer : http://stackoverflow.com/questions/8560440/removing-duplicate-columns-and-rows-from-a-numpy-2d-array 
def unique_rows(a): 
    a = np.ascontiguousarray(a) 
    unique_a = np.unique(a.view([('', a.dtype)]*a.shape[1])) 
    return unique_a.view(a.dtype).reshape((unique_a.shape[0], a.shape[1])) 

img=cv2.imread(your_image) 

#listing all pixels 
pixels=[] 
for p in img: 
    for k in p: 
     pixels.append(k) 

#finding all different colors 
colors=unique_rows(pixels) 

#comparing each color to every pixel 
res=np.zeros(img.shape) 
cpt=0 
for color in colors: 
    for i in range(img.shape[0]): 
     for j in range(img.shape[1]): 
      if (img[i,j,:]==color).all(): #if pixel is this color 
       res[i,j,:]=[0,0,cpt] #set the pixel to [0,0,counter] 
    cpt+=1 
1

あなたはnp.uniqueを使用することができます。..特にピクセルによって画像全体のピクセルを通過する、改善することができる多くはない非常にnumpyのも非常にOpenCVのですが、私はどのようにしきい値を正確に覚えていて、RGBの画素を交換するのが面倒でしたトリックのビットを有する:画素数が色の数よりもはるかに大きい場合

import numpy as np 

def safe_method(image, k): 
    # a bit of black magic to make np.unique handle triplets 
    out = np.zeros(image.shape[:-1], dtype=np.int32) 
    out8 = out.view(np.int8) 
    # should really check endianness here 
    out8.reshape(image.shape[:-1] + (4,))[..., 1:] = image 
    uniq, map_ = np.unique(out, return_inverse=True) 
    assert uniq.size == k 
    map_.shape = image.shape[:-1] 
    # map_ contains the desired result. However, order of colours is most 
    # probably different from original 
    colours = uniq.view(np.uint8).reshape(-1, 4)[:, 1:] 
    return colours, map_ 

しかし、 以下の発見的アルゴリズムは、巨大なスピードアップを実現してもよいです。 安価なハッシュ関数(赤いチャネルだけを見ているなど)を見つけようとします。それが成功した場合は、それを使ってルックアップテーブルを作成します。そうでない場合は、上記の安全な方法に戻ります。

CHEAP_HASHES = [lambda x: x[..., 0], lambda x: x[..., 1], lambda x: x[..., 2]] 

def fast_method(image, k): 
    # find all colours 
    chunk = int(4 * k * np.log(k)) + 1 
    colours = set() 
    for chunk_start in range(0, image.size // 3, chunk): 
     colours |= set(
      map(tuple, image.reshape(-1,3)[chunk_start:chunk_start+chunk])) 
     if len(colours) == k: 
      break 
    colours = np.array(sorted(colours)) 
    # find hash method 
    for method in CHEAP_HASHES: 
     if len(set(method(colours))) == k: 
      break 
    else: 
     safe_method(image, k) 
    # create lookup table 
    hashed = method(colours) 
    # should really provide for unexpected colours here 
    lookup = np.empty((hashed.max() + 1,), int) 
    lookup[hashed] = np.arange(k) 
    return colours, lookup[method(image)] 

テストとタイミング:

from timeit import timeit 

def create_image(k, M, N): 
    colours = np.random.randint(0, 256, (k, 3)).astype(np.uint8) 
    map_ = np.random.randint(0, k, (M, N)) 
    image = colours[map_, :] 
    return colours, map_, image 

k, M, N = 12, 1000, 1000 

colours, map_, image = create_image(k, M, N) 

for f in fast_method, safe_method: 
    print('{:16s} {:10.6f} ms'.format(f.__name__, timeit(
     lambda: f(image, k), number=10)*100)) 
    rec_colours, rec_map_ = f(image, k) 
    print('solution correct:', np.all(rec_colours[rec_map_, :] == image)) 

サンプル出力(12色、1000×1000ピクセル):

fast_method  3.425885 ms 
solution correct: True 
safe_method  73.622813 ms 
solution correct: True 
+0

safe_method()が機能しました。 fast_method()は 'TypeError: 'というエラーをスローします。numpy.ndarray'オブジェクトは最初の' for'ループで呼び出すことができません。 –

+0

@FatehSingh Hm、あなたは組み込み関数をシャドウしませんでしたか?限り、私が見ることができる限り、そのループ内の関数呼び出しは 'range、set、map、tuple'と' len'(私たちは 'image.reshape'を除外することができます)です。それらのうちの1つが配列かどうか確認してください。その場合は、配列の名前を別の名前に変更する必要があります。あなたは 'built builtins'を使って組み込み関数を取得し、' map = builtins.map'のように戻すことができます。 –

+0

ええ、それは働いた、それは問題を引き起こしていた名前の衝突だった。 –

関連する問題