2017-02-10 62 views
2

我的任務是編寫一個程序,從我的火箭俱樂部的高度檢測和區分三個「目標」。這些目標是我擁有RGB值的3大油布。Python和OpenCV圖像目標檢測和分化

當我開始這個項目時,我用三個矩形覆蓋了一個GoogleEarth圖像,使用防水布的精確RGB值,我的代碼完美無瑕地工作。但是,當我實際收到油布並開始在地面上拍攝照片時,我的代碼無法識別帶有我規定的RGB顏色邊界的油布。

我試圖將圖像轉換爲HSV色彩空間,但我只是不能得到它的工作。我也考慮過使用輪廓 - 試圖讓程序識別綁定每個目標的4條直線。問題是這些圖像將在戶外拍攝,所以我無法控制環境照明條件。

有沒有人有任何想法,什麼顏色空間或計算機視覺方法將允許我識別和區分這些目標,無論戶外照明?

獨創的圖像處理
Original Image After Processing 實際防水布之後被識別
Actual Tarps to be Identified

下面是代碼:

import cv2 
import numpy as np 

image = cv2.imread('2000 ft.png', 1) 
#hsv_img = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) 


#cv2.waitKey(0) 
cv2.destroyAllWindows() 

# define target strings 
targ = ['Target 1 - Blue', 'Target 2 - Yellow', 'Target 3 - Red'] 
i = 0 

# BGR boundaries of colors 
boundaries = [ 
# 0, 32, 91 
    ([40, 10, 0], [160, 60, 20]), 
# 255, 209, 0 
    ([0, 180, 220], [20, 230, 255]), 
# 166, 9, 61 
    ([40, 0, 150], [80, 30, 185]), 
] 

# colors for rectangle outlines 
colors = [ 
      ([91, 32, 0]), ([0, 209, 255]), ([61, 9, 166]) 
] 

# # loop over the boundaries 
for (lower, upper) in boundaries: 

    # create NumPy arrays from the boundaries 
    lower = np.array(lower, dtype = "uint16") 
    upper = np.array(upper, dtype = "uint16") 

    # find the colors within the specified boundaries and apply 
    # the mask 
    mask = cv2.inRange(image, lower, upper) 
    output = cv2.bitwise_and(image, image, mask = mask) 
    # frame threshold 
    frame_threshed = cv2.inRange(image, lower, upper) 
    imgray = frame_threshed 

    # iteratively view masks 
    cv2.imshow('imgray',imgray) 
    cv2.waitKey(0) 
    cv2.destroyAllWindows() 

    ret,thresh = cv2.threshold(frame_threshed,127,255,0) 
    contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) 

    # Find the index of the largest contour 
    areas = [cv2.contourArea(c) for c in contours] 
    max_index = np.argmax(areas) 
    cont=contours[max_index] 

    # putting text and outline rectangles on image 
    x,y,w,h = cv2.boundingRect(cont) 
    cv2.rectangle(image,(x,y),(x+w,y+h),colors[i],2) 
    cv2.putText(image, targ[i], (x-50, y-10), cv2.FONT_HERSHEY_PLAIN, 0.85, (0, 255, 0)) 
    # cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),4) 
    cv2.imshow("Show",image) 
    cv2.waitKey() 
    cv2.destroyAllWindows() 
    i += 1 

cv2.destroyAllWindows() 

我用Python寫的代碼,我有一個良好的金額的經驗,使用我沒有太多經驗的OpenCV庫。任何幫助將不勝感激!

回答

0

從相機顏色(實際上,從火箭)將依賴於環境光,並且將不會是

# colors for rectangle outlines 
colors = [ 
      ([91, 32, 0]), ([0, 209, 255]), ([61, 9, 166]) 
] 

您可以檢查通過計算圖像的像素座標,並做了打印val。

如果仍然可以更改標記,我會使用對比度較大的標記而不是單一顏色(例如帶有白色邊框的藍色方塊等),這將便於canny> findContour,然後使用approxpoly查找正方形。

如果改變標記是不行的話,那麼最好的辦法是分開R,G和B通道,然後執行canny> findcontour。我懷疑紅色和藍色的廣場會好起來,但黃色的廣場會變得很差,因爲它融入了風景。

0

我提出的代碼python3/OpenCV3,否則它是根據你的代碼

@pandamakes是正確的,他的要求。你需要尋找接近目標值的像素,但你不能認爲你會得到非常接近該值的東西。

我添加了一個用於忽略邊界的掩碼(在那裏你會得到很多僞像),並且我修改了目標值,因爲在現實生活中,你不可能獲得具有零值的像素(特別是在你有大氣的空間圖像中反射)

基本上我尋找一個區域與值接近目標值,並使用洪水填充定位實際的目標邊界

編輯  從RGB色彩空間移動到的CIELab,只使用用於增強照明條件的AB色通道

import cv2 
import numpy as np 

image = cv2.imread('tarpsB.jpg', 1) 
#convert to CIELab 
cielab = cv2.cvtColor(image, cv2.COLOR_BGR2Lab) 

# define target strings 
targ = ['Target 1 - Blue', 'Target 2 - Yellow', 'Target 3 - Red'] 
i = 0 

# colors = [ 
#   ([91, 40, 40]), ([40, 209, 255]), ([81, 60, 166]) 
# ] 
# rough conversion of BGR target values to CIELab 
cielab_colors = [ 
      ([20, 20, -40]), ([80, 0, 90]), ([40, 70, 30]) 
] 

# # loop over the boundaries 
height = image.shape[0] 
width = image.shape[1] 
mask = np.ones(image.shape[0:2]) 

cv2.circle(mask, (int(width/2), int(height/2)), int(height/2), 0, -1); 
mask = 1-mask 
mask = mask.astype('uint8') 

#for color in colors: 
for cielab_color in cielab_colors: 
    diff_img = cielab.astype(float) 
    # find the colors within the specified boundaries and apply 
    # the mask 

    diff_img[:, :, 0] = np.absolute(diff_img[:, :, 0] - 255 * cielab_color[0]/100) 
    diff_img[:, :, 1] = np.absolute(diff_img[:, :, 1] - (cielab_color[1] + 128)) 
    diff_img[:, :, 2] = np.absolute(diff_img[:, :, 2] - (cielab_color[2] + 128)) 


    diff_img = (diff_img[:, :, 1] + diff_img[:, :, 2])/2 
    diff_img = cv2.GaussianBlur(diff_img, (19, 19), 0) 
    minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(diff_img, mask) 
    min_img = np.array(diff_img/255) 

    ff_mask = np.zeros((height + 2, width + 2), np.uint8) 
    cv2.floodFill(image, ff_mask, minLoc, 255, (12, 12, 12), (12, 12, 12), cv2.FLOODFILL_MASK_ONLY); 
    ff_mask = ff_mask[1:-1, 1:-1] 
    im2, contours, hierarchy = cv2.findContours(ff_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 

    # Find the index of the largest contour 
    areas = [cv2.contourArea(c) for c in contours] 
    max_index = np.argmax(areas) 
    cont=contours[max_index] 
    print('target color = {}'.format(image[minLoc[1], minLoc[0], :])) 
    # putting text and outline rectangles on image 
    x,y,w,h = cv2.boundingRect(cont) 
    cv2.rectangle(image,(x,y),(x+w,y+h),colors[i],2) 
    cv2.putText(image, targ[i], (x-50, y-10), cv2.FONT_HERSHEY_PLAIN, 0.85, (0, 255, 0)) 

    cv2.imshow('diff1D',diff_img/255) 
    cv2.imshow('ff_mask',ff_mask*255) 
    cv2.waitKey(0) 
    i += 1 

cv2.imshow("Show",image) 
cv2.waitKey(0) 

cv2.destroyAllWindows() 

編輯將輸出圖像

enter image description here

+0

羅莎您好,我用這個代碼,它與我最初發布的圖像的偉大工程。不過,我今天拍攝了更多樣本圖片,紅色和藍色目標未被識別。不同的顏色邊界是否有助於識別這些目標?下面是我試圖分析的圖片之一:http://www.jpeg-optimizer.com/uploaded_images_final/IMG_2654__1486844593_152.7.224.5.jpg – RB1994

+0

理想情況下,您應該瞭解目標顏色,但我認爲如果您要採樣顏色從幾個(非連續)幀,並設置目標顏色的樣本的意思,你會得到合理的結果 –

+0

無論如何,我更新代碼使用CIELab而不是RGB,它應該更好地工作 –