2016-04-08 41 views
3

私は画像処理の新人であり、問​​題を抱えています。色が輪郭内にあるかどうかを調べるOpenCV

enter image description here

私の目標が存在しない場合は、セルと0内部の赤がある場合に1と行列にそれを有効にすることです:私はこのイメージを持っています。

これはだからそれは輪郭を抽出し、4つの隅エッジの座標(x、y)を決定するためにapproxPolyDPを使用することができ、私のコードを有する

10000000000 
10001000000 
10001000000 
10001000000 
11111111111 
10000000101 
10111111101 
etc... 

あろう。

Contours shown in white

今は特定の色(赤)各輪郭内にあるかどうかを決定する方法を見つけ出す必要があります。

私のコードの一部です:うまくいけば誰かが助けることができます!

def extract_cells(grid): 
    #convert to gray 
    image_gray = cv2.cvtColor(grid, cv2.COLOR_BGR2GRAY) 
    #creates a binary image from the gray scale image to use as input for findContours() 
    #thresh = cv2.adaptiveThreshold(image_gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY_INV,11,15) 

    #Find countors 
    tempimg, contours, hierarchy = cv2.findContours(image_gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) 

    #draw all countours 
    count = 0 
    max_size = 0 
    matrix = [] 
    new_contours = [] 
    grid_contour = 0 
    grid_contour_row = None 
    grid_contour_column = None 
    for each in enumerate(contours): 

     #used to find the midpoint of each cell 
     M = cv2.moments(contours[count]) 
     row = int(M['m10']/M['m00']) 
     column = int(M['m01']/M['m00']) 

     #find biggest box (this is the grid itself, so needs to be removed since it is not a cell) 
     size = cv2.contourArea(contours[count]) 
     if (size > max_size): 
      new_contours.append(contours[grid_contour]) 
      #put a marker in each cell for testing 
      #if (grid_contour_row != None and grid_contour_column != None): 
       #cv2.putText(grid, "0", (grid_contour_row, grid_contour_column), cv2.FONT_HERSHEY_SIMPLEX, 1, (255,255,255)) 
      grid_contour = count 
      grid_contour_row = row 
      grid_contour_column = column 
     else: 
      new_contours.append(contours[count]) 
      #put a marker in each cell for testing 
      #cv2.putText(grid, "0", (row, column), cv2.FONT_HERSHEY_SIMPLEX, 1, (255,255,255)) 

     #matrix = create_matrix(matrix,count) 
     count += 1 

    #draw white lines showing contours 
    cv2.drawContours(grid, new_contours, -1, (255,255,255)) 

    #approx contains x,y coordinates for the 4 corners of the cell 
    approx = cv2.approxPolyDP(contours[0],0.01*cv2.arcLength(contours[0],True),True) 

    cv2.imshow("test", grid) 
    cv2.waitKey(0) 
    return new_contours, approx 


def identify_colors(image, *colors): 
    colorlist = [] 
    #Add RGB values for each color specified when the function was called 
    #to the list colorlist 

    if "blue" in colors: 
     colorlist.append(([115,0,0], [255,100,100])) 
    if "white" in colors: 
     colorlist.append(([215, 215, 215], [255, 255, 255])) 
    if "red" in colors: 
     colorlist.append(([0,0,100], [100,100,255])) 
    if "green" in colors: 
     colorlist.append(([0,115,0], [100,255,100])) 

    #loop over the colorlist 
    for (lower, upper) in colorlist: 
     # create NumPy arrays from the colorlist 
     lower = np.array(lower, dtype = "uint8") 
     upper = np.array(upper, dtype = "uint8") 

     #econverts image to b/w with white being anything in the BGR value range 
     mask = cv2.inRange(image, lower, upper) 
     #converts that specified range back to its orginal color 
     output = cv2.bitwise_and(image, image, mask = mask) 

     #show the photos side by side 
     #cv2.imshow("images", np.hstack([image, output])) 
     #cv2.waitKey(0) 

    return output 
+0

だから、私の理解では、あなたは右、それぞれ "ホワイトボックス" エッジ座標がありますか?見つけた各白いボックスにループし、各ボックスについて、赤いピクセルに対して元の画像を(ボックスの座標を使用して)調べます。新しいマットを作成して元の画像を切り抜く(コピーする)ために白いボックスの座標を使用することさえできます - 赤いピクセルのためにクロップされたマットを見ることができます... –

+0

これも私が考えていたものです。しかし、私は座標を使ってイメージをどのようにループするのか分かりません。あなたは例を挙げることができると思いますか?申し訳ありませんが、これはまったく新しいものです:) – Ashley

+0

小さなボックスのエッジコーディネートを使用すると、イメージマトリックスでこれをアドレス指定するだけで、interes/ROIのサブイメージ/領域を抽出する必要があります。その部分画像では、(cv2.inrangeを使って)色を探すことができます。 http://docs.opencv.org/3.1.0/d6/d00/tutorial_py_root.html#gsc.tab=0 – tfv

答えて

3

あなたがscipy.ndimage.label()を使用する場合、それははるかに簡単です:

from scipy import ndimage 
import cv2 
import numpy as np 
import pandas as pd 

img = cv2.imread("image.png") 

blue = np.array([200, 70, 60]) 
red = np.array([30, 20, 220]) 

isblue = cv2.inRange(img, blue, blue+20) 
isred = cv2.inRange(img, red, red+20) > 0 

labels, count = ndimage.label(~isblue) 

loc = np.where(labels >= 2) #label 1 is the border 

# to get the location, we need to sort the block along yaxis and xaxis 
df = pd.DataFrame({"y":loc[0], "x":loc[1], "label":labels[loc], "isred":isred[loc]}) 

grid = df.groupby("label").mean().sort_values("y") 

def f(df): 
    return df.sort_values("x").reset_index(drop=True) 
res = grid.groupby((grid.y.diff().fillna(0) > 10).cumsum()).apply(f) 

print((res.isred.unstack(1) > 0).astype(np.uint8)) 

出力:

0 1 2 3 4 5 6 7 8 9 10 
y            
0 1 0 0 0 0 0 0 0 0 0 0 
1 1 0 0 0 1 0 0 0 0 0 0 
2 1 0 0 0 1 0 0 0 0 0 0 
3 1 0 0 0 1 0 0 0 0 0 0 
4 1 1 1 1 1 1 1 1 1 1 1 
5 1 0 0 0 0 0 0 1 1 1 1 
6 1 0 1 1 1 1 1 1 1 0 1 
7 0 0 0 0 0 0 0 0 0 0 1 
8 0 0 0 0 0 0 0 0 0 0 1 
9 0 0 0 0 0 0 0 0 0 0 1 
10 0 0 0 0 0 0 0 0 0 0 1 
+1

のチュートリアルをご覧ください。私はそのアプローチが好きです、ありがとう、何かを学んだことがあります! – tfv

0
次のように作業を進めることができ

  • は天気をを見て、輪郭を4を作成し、赤いマスクからのそれぞれの単一の小さな正方形の
  • を青マスクから赤と青のカラー
  • のためのマスクを作成赤のピクセルは小さな四角形です

結果は次のようになります。

enter image description here

コメント付きのコード。

リストを印刷するリストから行列を生成する必要があることがわかりました。各四角形には、リストに0または1が含まれ、その四角形の重心のx/y座標が含まれています。残念なことに、輪郭は、形状の不規則性が小さいため、「通常の」順序でソートされないため、あなた自身で座標のソートを行う必要があります。残念です。

これを避けたい場合は、通常のグリッドから生成されたシードでフラッドフィルを行い、そのグリッドをループしてmask2を生成することもできます。

import cv2 
import numpy as np 
img = cv2.imread('image.png') 


# Define range of blue color 
lower_limit = np.array([204,72,63]) 
upper_limit = np.array([204,72,63]) 

# Generate mask for the blue pixels 
blue_colour_mask = cv2.inRange(img, lower_limit, upper_limit) 

# Define range of red color 
lower_limit = np.array([36,28,237]) 
upper_limit = np.array([36,28,237]) 

# Generate mask for the red pixels 
red_colour_mask = cv2.inRange(img, lower_limit, upper_limit) 


# Remove outer black area 
flooded = img.copy() 
x = 5 
y = 5 
flooded = blue_colour_mask.copy() 
h, w = blue_colour_mask.shape[:2] 
mask = np.zeros((h+2, w+2), np.uint8) 
mask[:] = 0 
cv2.floodFill(flooded,mask,(x,y),(255,)*3, (40,)*3, (40,)*3, 4) 


# Loop through each single small rectange (contour # from 1 to 121, 0 ist image border) 
_, contours, hierarchy = cv2.findContours(flooded.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) 
h, w = img.shape[:2] 

result= np.zeros((h, w, 3), np.uint8) 
result[:] = 0 

mask2 = np.zeros((h, w), np.uint8) 
list =[] 

for i in range(1,122): 
    mask2[:] = 0 
    cv2.drawContours(mask2, contours, i, (255,255,255), cv2.FILLED) 
    mask3= cv2.bitwise_and(mask2, red_colour_mask) 
    pixnumber= cv2.countNonZero(mask3) 

    if pixnumber == 0: 
     cv2.drawContours(result, contours, i, (255,255,255), cv2.FILLED) 
     moments = cv2.moments(contours[i]) 
     cx = int(moments['m10']/moments['m00']) 
     cy = int(moments['m01']/moments['m00']) 
     print 0, i, cx, cy 
     list.append([0,cx, cy]) 
    else: 
     cv2.drawContours(result, contours, i, (0,0,255), cv2.FILLED) 
     moments = cv2.moments(contours[i]) 
     cx = int(moments['m10']/moments['m00']) 
     cy = int(moments['m01']/moments['m00'])  
     print 1, i, cx, cy 
     list.append([0,cx, cy]) 

cv2.imshow('Result',result) 

cv2.waitKey(0) 

print list 


cv2.imshow('image',img) 
cv2.imshow('Blue pixel mask',blue_colour_mask) 
cv2.imshow('Red pixel mask',red_colour_mask) 
cv2.imshow('Result',result) 

cv2.waitKey(0) 
0
import cv2 
import numpy as np 


def centroid(contour): 
    x,y,w,h = cv2.boundingRect(contour) 
    return (y+h/2.0, x+w/2.0) 

def contains_red(red_mask, tile): 
    tile_area = np.zeros_like(red_mask) 
    cv2.drawContours(tile_area, [tile[1]], 0, 255, -1) 
    red_tile_area = cv2.bitwise_and(tile_area, red_mask) 
    return (cv2.countNonZero(red_tile_area) > 0) 

def get_transform(grid_size, grid_contour): 
    x,y,w,h = cv2.boundingRect(grid_contour) 
    tile_w = float(w)/(grid_size[0]) 
    tile_h = float(h)/ (grid_size[1]) 
    return ((-y - tile_h/2, -x - tile_w/2), (1/tile_h, 1/tile_w)) 


img = cv2.imread("input.png") 

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) 
h, s, v = cv2.split(hsv) 

cv2.imwrite("out_1.png", np.hstack([h, s, v])) 

# Saturation mask to get rid of black 
s_mask = cv2.threshold(s, 10, 255, cv2.THRESH_BINARY)[1] 

# Pick out blue area 
blue_range = [110, 130] 
blue_mask = cv2.inRange(h, blue_range[0], blue_range[1]) 
blue_mask = cv2.bitwise_and(blue_mask, s_mask) 


# Pick out blue area 
red_range = [[170, 180], [0,10]] 
red_mask = cv2.bitwise_or(
    cv2.inRange(h, red_range[0][0], red_range[0][1]) 
    , cv2.inRange(h, red_range[1][0], red_range[1][1])) 
red_mask = cv2.bitwise_and(red_mask, s_mask) 

cv2.imwrite("out_2.png", np.hstack([s_mask, blue_mask, red_mask])) 


kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) 
# Remove noise 
blue_mask = cv2.morphologyEx(blue_mask, cv2.MORPH_OPEN, kernel) 
# Fill any small holes 
blue_mask = cv2.morphologyEx(blue_mask, cv2.MORPH_CLOSE, kernel) 


# Find outer contour, and fill area outside 
cnt_grid = cv2.findContours(blue_mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0] 
assert(len(cnt_grid) == 1) 
grid_area = np.zeros_like(blue_mask) 
cv2.drawContours(grid_area, cnt_grid, 0, 255, -1) 
grid_tiles = cv2.bitwise_and(cv2.bitwise_not(blue_mask), grid_area) 

cv2.imwrite("out_3.png", np.hstack([blue_mask, grid_area, grid_tiles])) 

# Find contours of our tiles 
cnt_tiles = cv2.findContours(grid_tiles.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0] 

# Find scaling parameters 
offset, scale = get_transform((11, 11), cnt_grid[0]) 

tiles = [[centroid(contour), contour, False] for contour in cnt_tiles] 
for tile in tiles: 
    # Rescale centroid 
    tile[0] = (
     int(round((tile[0][0] + offset[0]) * scale[0])) 
     , int(round((tile[0][1] + offset[1]) * scale[1])) 
    ) 
    tile[2] = contains_red(red_mask, tile) 

# Sort the tiles 
tiles = sorted(tiles, key=lambda x: x[0], reverse=False) 

# Extract the results 
result = np.array([int(t[2]) for t in tiles]) 

print result.reshape(11,11) 

我々は最初のHSV色空間に画像を分割します。

色相、彩度、値のチャネルは:ブラックは、任意の色相を終わることができるので

enter image description here

、我々は、不飽和画素を無視すべきです。

次に、範囲内、ビット単位、および飽和マスクを使用して、青と赤のマスクを抽出できます。

彩度は、青と赤のマスクをマスク:

enter image description here

私たちは、形態学的開口部を適用し、ノイズを取り除くために閉じます。

グリッド自体の領域は、外側の輪郭を取得して識別します。

次に、倒立した画像に外郭をつけてタイル領域を特定します。

ブルーマスク、グリッド領域マスク、タイルマスク:

enter image description here

次の我々は、タイルの重心を計算します。

タイルグリッドサイズは一定であると仮定します。グリッドバウンディングボックスの座標に基づいて、スケーリングとオフセットを決定し、重心を0..10の範囲に再サンプリングすることができます。

次に、重心座標でタイルを並べ替え、結果を得るためにタイルを再形成することができます。

結果:

[[1 0 0 0 0 0 0 0 0 0 0] 
[1 0 0 0 1 0 0 0 0 0 0] 
[1 0 0 0 1 0 0 0 0 0 0] 
[1 0 0 0 1 0 0 0 0 0 0] 
[1 1 1 1 1 1 1 1 1 1 1] 
[1 0 0 0 0 0 0 0 1 1 1] 
[1 0 1 1 1 1 1 1 1 0 1] 
[0 0 0 0 0 0 0 0 0 0 1] 
[0 0 0 0 0 0 0 0 0 0 1] 
[0 0 0 0 0 0 0 0 0 0 1] 
[0 0 0 0 0 0 0 0 0 0 1]] 
関連する問題