LoginSignup
1
3

More than 1 year has passed since last update.

NO.3取得したいろが 何色なのか 区別する

Last updated at Posted at 2021-06-12
前回の記事

NO.1 カメラ起動+BGR取得
NO.2 ウィンドウに取得した色を表示
NO.4ルービックキューブの回転記号をえる
NO.5 最終コード 参考程度に,,,,

取得したいろが 何色なのか 区別する

ふたつの 方法があるです

ひとつめ、BGRの範囲を指定して その範囲内なら 特定の色をかえす

取得した BGR [10, 20, 180] 赤色

Low[0, 0, 100]
Up[50, 50, 255]
Low < BGR < Up

Lowより 大きくて Upより 小さい この場合は 赤色ですよーとする

Low = [0, 0, 100]
BGR = [10, 20, 180]
Up = [50, 50, 255]

if Low[0] < BGR[0] and BGR[0] < Up[0]:
  if Low[1] < BGR[1] and BGR[1] < Up[1]:
    if Low[2] < BGR[2] and BGR[2] < Up[2]:
      print("True")

#True
----------------------------------------------------

Low = [0, 0, 100]
BGR = [10, 80, 180]
Up = [50, 50, 255]

#もし このように BGR[1](80) が Up(50)より 大きいと 最後までいかず Trueが表示されません

このように 範囲を指定してあげて このときは この色と あの色 としてあげればよいです。

しかし 部屋の明るさ などで かなり こまかくかわるため 範囲の指定がすごく難しいです。
オレンジと赤は 同じような 値になりやすかったりするので。

メリット
処理が軽い、コードが短い
デメリット
色の取得が難しくなる。 環境に左右されやすい(明るさ)




ふたつめ、色のデータ[B,G,R]をあつめる

範囲で指定しないで [B,G,R]このデータを たっくさんあつめて
取得したBGRと一致したら色を返す方法

green_list = [[68, 73, 41],[59, 73, 40],[58, 75, 35],[66, 77, 40]]
BGR = [59, 73, 40]

for i in green_list:
  if i == BGR:
    print("BGRはgreenです")
    break
  else:
    print("False")

#greenリストの二つ目の [59, 73, 40] が BGR = [59, 73, 40]と一致
"BGRはgreenです" #とかえってきます。

データにないものは 色を返さないので 精度はかなりよくなりますが
そうとうな データが必要になります。
単純に 256×256×256 = 16777216個
[0,0,0],[0,0,1] こんなデータが 16777216個あるので
仮に これを for文で ひとつづつまわしたら すっごいしんどいです


メリット
色の取得制度が高い。 環境に左右されにくい(データ量次第)
1色(赤で 4万通りくらいのデータがあったらまぁまぁ精度よかったです 9/10くらいは成功

デメリット
処理が激重、コードが激長


ひとつめのBGRの範囲を指定して特定の色をかえす

今回は これを やります。
(データーをたくさん 取得するのは 別の記事で書くかもしれません)

サンプルコード(指定した範囲に 取得したBGRがあてはまるか)

color_key = ['black','black','black',
            'black','black','black',
            'black','black','black']

color_index =[[0,0,0],[0,0,0],[0,0,0],
            [0,0,0],[0,0,0],[0,0,0],
            [0,0,0],[0,0,0],[0,0,0]]

colors_BGR = {
  'red': ([5, 20, 160], [75, 90, 189]),    
  'green': ([25, 130, 0], [100, 180, 30]),    
  'white': ([130, 130, 130], [255, 255, 255]), 
  'blue': ([140, 80, 0], [255, 180, 50]),   
  'orange': ([5, 91, 190], [130, 150, 255]),  
  'yellow': ([5, 150, 150], [110, 200, 200])   
   }

BGR = [20, 70, 180]

for color, ( lower, upper) in colors_BGR.items():
  if lower[0] < BGR[0] and BGR[0] < upper[0]:
    if lower[1] < BGR[1] and BGR[1] < upper[1]:
      if lower[2] < BGR[2] and BGR[2] < upper[2]:
          color_key[0] = color
          color_index[0] = BGR


#-----------------------------------------------------
#実行したあと
for 'red', ( [5, 20, 160], [75, 90, 189]) in colors_BGR.items():
  if 5 < 20 and 20 < 75:
    if 20 < 70 and 70 < 90:
      if 160 < 180 and 180 < 189:
          color_key[0] = 'red'
          color_index[0] = [20, 70, 180]

#color_index = [[20, 70, 180], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
#color_key = ['red', 'black', 'black', 'black', 'black', 'black', 'black', 'black', 'black']





 .items()
辞書型を展開するのに もってこいです。
画像のように してくれます
lowe[5,20,160] BGR[20, 70, 160] upper[75, 90, 189]
BGRが lowerとuperの間に入ってるか[0]インデックス ひとつごと 確認します

lowe[5, -, -] < BGR[20, -, -] < upper[75, -, -]
OKだったら [1]にいきます
lower[-, 20, -] < BGR[-, 70, -] < upper[-, 90, -]
OKだったら[2] (省略

もし どこか [0],[1],[2]で BGRが範囲外だったら次の グリーンを確認します
'green': ([25, 130, 0], [100, 180, 30]
だめだったらwhite blue、、、順番に探します

NO3 サンプル2-2.png

今回は redが 指定した範囲のなかになってるので
color_key[0] = 'red'
color_index[0] = [20, 70, 180]

color_index = [[20, 70, 180], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
color_key = ['red', 'black', 'black', 'black', 'black', 'black', 'black', 'black', 'black']
リストに追加されます。






サンプルコード(指定した範囲に 取得したBGRがあてはまるか キューブ色を取得)

import cv2

capture = cv2.VideoCapture(2)
capture.set(cv2.CAP_PROP_FRAME_WIDTH, 1080) # 横幅
capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) # 縦幅

color_index =[[0,0,0],[0,0,0],[0,0,0],
            [0,0,0],[0,0,0],[0,0,0],
            [0,0,0],[0,0,0],[0,0,0]]

color_key = ['black','black','black',
            'black','black','black',
            'black','black','black']

colors_BGR = {
  'red': ([5, 20, 160], [75, 90, 189]),      #red     6  4   
  'green': ([25, 130, 0], [100, 180, 30]),     #green   3  2
  'white': ([130, 130, 130], [255, 255, 255]), #white   2  3
  'blue': ([140, 80, 0], [255, 180, 50]),     #blue    5  5
  'orange': ([5, 91, 190], [130, 150, 255]),    #orange  4  1
  'yellow': ([5, 150, 150], [110, 200, 200])    #yellow  1  0
   }

#Y縦 X横
frame_xy = [[300, 300],[300, 450],[300, 600],
            [450, 300],[450, 450],[450, 600],
            [600, 300],[600, 450],[600, 600]]

x_start = [280, 430, 580, 280, 430, 580, 280, 430, 580]
y_start = [280, 280, 280, 430, 430, 430, 580, 580, 580]
x_end   = [320, 470, 620, 320, 470, 620, 320, 470, 620]
y_end   = [320, 320, 320, 470, 470, 470, 620, 620, 620]

x_start2 = [30, 80, 130, 30, 80, 130, 30, 80, 130]
y_start2  = [30, 30, 30, 80, 80, 80, 130, 130, 130]
x_end2   = [70, 120, 170, 70, 120, 170, 70, 120, 170]
y_end2   = [70, 70, 70, 120, 120, 120, 170, 170, 170]


while True:
    ret, frame = capture.read()

    for k, (xs, ys, xe, ye, xs2, ys2, xe2, ye2) in enumerate(zip
            (x_start, y_start, x_end, y_end, x_start2, y_start2, x_end2, y_end2)):

        cv2.rectangle(frame, (xs, ys), (xe, ye), (255, 255, 255), 2)

        b1 = color_index[k][0]
        g1 = color_index[k][1]
        r1 = color_index[k][2]
        cv2.putText(frame, str(k), (xs2, ys2), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,0), 2)

        if color_key[k] == 'red':
          b1, g1 ,r1 = 0, 0, 255

        elif color_key[k] == 'green':
          b1, g1 ,r1 = 0, 255, 0

        elif color_key[k] == 'white':
          b1, g1 ,r1 = 255, 255, 255

        elif color_key[k] == 'blue':
          b1, g1 ,r1 = 255, 0, 0

        elif color_key[k] == 'orange':
          b1, g1 ,r1 = 0, 128, 255

        elif color_key[k] == 'yellow':
          b1, g1 ,r1 = 0, 255, 255

        #左上に 色を表示する
        cv2.rectangle(frame, (xs2, ys2), (xe2, ye2), (int(b1), int(g1), int(r1)), -1)

        #BGRの取得位置
        for i, (x, y) in enumerate(frame_xy):
          pixel = frame[x, y]
          b = pixel[0]
          g = pixel[1]
          r = pixel[2]
          BGR = [b,g,r] 
          color_index[i] = BGR

          #colors_BGRの範囲内に 真上のBGRがはいってるか 確認
          for color, ( lower, upper) in colors_BGR.items():
              if lower[0] < BGR[0] and BGR[0] < upper[0]:
                if lower[1] < BGR[1] and BGR[1] < upper[1]:
                  if lower[2] < BGR[2] and BGR[2] < upper[2]:
                      color_key[i] = color
                      color_index[i] = BGR
                      if color_key[i] != 'black':
                        #print(color_key) 
                        #print(color_index)
                        pass

    cv2.imshow('camra',frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

capture.release()
cv2.destroyAllWindows()

if color_key[i] != 'black':
print(color_key)
print(color_index)
コードの下のほうに これがあります
print(color_index)これをすれば つねに 取得したBGRをみれるので
赤色は、緑色は、、、青色は、、 色の範囲の指定に役立ちます



サンプルコード(指定した範囲に 取得したBGRがあてはまるか キューブ色を取得)を実行

これは うまくいってるほうです
NO.3 サンプル3.PNG




 

BGRの範囲を指定して その範囲内なら 特定の色をかえすのむずかしさが下です

実際のところ
5番と7番が色が違っています。 環境でかなりかわります 精度がひくい。
NO.3 サンプル3-1.PNG

この制度の低さを 解消するには 環境に左右されないようにすれば かなり精度がよくなります。
周りから 光をいれずに 一定の光量を キューブにあてればよいのです。





ルービックキューブの台をつくり(3Dプリンター) 型紙とかでも つくれると思います(そのときは 必ず白色にしてくだい
かつ光が反射しない素材がいいです、、、ルービックキューブもテカテカしてるものだと 光があたると 白っぽくなってしまうのでなかなか精度がだしにくくなります。)
下からスマートフォンをいれて カメラを起動させてますライトをONにすれば あるていど 一定のあかるさになるので
これで 安定した BGRを取得することができます
NO.3 サンプル3ー2.PNG

ちなみに ルービックキューブはこれを使用してます。
Gancube xs

参考にしたサイトが見つからない、、、申し訳ない

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3