2017-02-10 1 views
2

Мне поручено написать программу для обнаружения и выделения трех «целей» с высоты для моего ракетного клуба. Этими целями являются 3 больших брезента, для которых у меня есть значения RGB.Определение и дифференцирование целевого изображения Python и OpenCV

Когда я начал этот проект, я наложил изображение GoogleEarth на 3 прямоугольника, используя точные значения 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 и последующую аппрополицию, чтобы найти квадраты.

Если менять маркеры нет, то, возможно, лучше всего отделить каналы R, G и B, а затем выполнить canny> findcontour. Я подозреваю, что красный и синий квадраты пройдут хорошо, но желтый квадрат пойдет плохо, так как он впишется в пейзаж.

0

Я переместил код Python3/OpenCV3, в противном случае он основан на коде

@pandamakes находится прямо в его претензии. Вам нужно искать пиксели, близкие к вашим целевым значениям, но вы не можете предположить, что получите то, что очень близко к этому значению.

Я добавил маску для игнорирования границ (у вас там много артефактов), и я изменил целевые значения, так как в реальной жизни вы вряд ли получите пиксели с нулевым значением (особенно на воздушном изображении, где у вас атмосферный отражение)

основном Ищу регион с величиной, близкой к целевому значению и используя поток заполнения для обнаружения фактических целевых границ

EDIT   перемещения из цветового пространства 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, он должен работать лучше –

Смежные вопросы