#python #numpy #opencv #image-processing #object-detection
#python #numpy #opencv #обработка изображений #обнаружение объектов
Вопрос:
Я работаю над проектом, в котором мне нужно обнаруживать цветные транспортные средства с высоты птичьего полета. Смотрите изображение-кадр ниже
Поскольку я считаю, что в этом случае глубокое обучение является излишним, я решил использовать классический конвейер обнаружения, применив метод обратной проекции гистограммы для обнаружения красного транспортного средства.
Код, который я использую, показан ниже
#import packages
import cv2
import numpy as np
import matplotlib.pyplot as plt
#defining disk for the convolution
disc = cv2.getStructuringElement(cv2.MORPH_RECT,(10,10))
#defining Kernel
kernel=cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
kernel1 = np.ones((5,5),np.uint8)
#preparing the object model by cropping the target object and reading it
Red_Model=cv2.imread(r'C:/Users/kjbaili/.spyder-py3/webcam_calib/red_new_uniform.png')
#convert object_model to hsv
hsv_red = cv2.cvtColor(Red_Model, cv2.COLOR_BGR2HSV)
cv2.imshow('HSV_Model',hsv_red)
#calculating histogram of object_model
M = cv2.calcHist([hsv_red],[0,1],None,[180,256],[0,180,0,256])
#reading the image where we want to search for the target object
img=cv2.imread(r'C:/Users/kjbaili/.spyder-py3/Mean_Shift/MST_with_3D_projection/messigray1.png')
#converting the image to hsv
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
#calculating histogram of image
I= cv2.calcHist([hsv_img],[0,1],None,[180,256],[0,180,0,256])
#calculating the ration histogram
R=M.copy() /I.copy()
#extracting the image channels
h,s,v = cv2.split(hsv_img.copy())
#backprojecting the R_red hist
B1 = R[h.ravel(),s.ravel()]
#reshaping the resulted vector into image and normalize the values between 0 and 1
B2=B1.reshape(hsv_img.copy().shape[:2])
B = np.minimum(B1.copy(),1)
B = B.reshape(hsv_img.copy().shape[:2])
#removing noises
open_B_red=cv2.morphologyEx(B.copy(),cv2.MORPH_OPEN,kernel)
Filter_red=cv2.filter2D(open_B_red.copy(),-1,disc,open_B_red)
#displaying results
cv2.imshow('Filter',Filter_red)
cv2.waitKey(0)
cv2.destroyAllWindows()
Алгоритм работает для проиллюстрированного изображения (см. Изображение маски результата)
Однако, когда цвета объекта совпадают с цветами фона, как на изображении ниже, он также обнаруживает мою футболку, он обнаруживает их оба и, таким образом, не распознает только целевой объект
Поэтому я подумал о использовании дополнительной функции наряду с функцией цвета для улучшения обнаружения, чтобы она все еще обнаруживала целевой объект, несмотря на небольшое сходство в цветах, и пришел к так называемому «Локальному двоичному шаблону-LBP«, который вычисляет текстуру объекта. На самом деле, я мог бы рассчитать LBP для объекта и изображения, однако не знаю, как интегрировать его с вышеуказанным методом, чтобы красный автомобиль обнаруживался с помощью обнаружения цвета и текстуры.
Поэтому я был бы очень признателен за идею о том, как улучшить обнаружение в таком случае, используядополнительные функции из LBP или даже другие дополнительные функции.
для получения информации о LBP, пожалуйста, смотрите:https://towardsdatascience.com/face-recognition-how-lbph-works-90ec258c3d6b
для получения информации о том, как работает обратная проекция гистограммы:https://theailearner.com/2019/04/18/histogram-backprojection /
Вот исходное изображение: Вот полученная маска
заранее спасибо
Комментарии:
1. В чем разница между футболкой и автомобилем? 1. Автомобиль представляет собой прямоугольник с постоянным соотношением w / h (~ 2-2,5). 2. Автомобиль имеет выпуклую форму. Вы можете попробовать использовать эти свойства.
2. Спасибо за комментарий. Вы имеете в виду, что я говорю алгоритму искать прямоугольные формы в полученном изображении маски вместо всего остального? ? @AlexAlex
3. Получите контуры из изображения маски. Затем фильтруйте по соотношению сторон и площади.
4. .Спасибо за комментарий. . Не могли бы вы выразить это на примере? . @fmw42
5. Редко бывает, что ваша футболка будет иметь тот же аспект и область. Итак, протестируйте, используя комбинацию аспекта и области. Автомобили будут почти одинакового размера.
Ответ №1:
Вот один из способов сделать это в Python / OpenCV. Первый порог для цвета. Затем примените некоторую морфологию для очистки посторонних областей. Затем получите контуры и выполните цикл над каждым из них. Вычислите повернутый прямоугольник для каждого и его площадь и соотношение сторон (наибольшее измерение / наименьшее измерение). Отфильтруйте контуры в диапазоне обоих и нарисуйте белый контур и белый повернутый прямоугольник на входном изображении.
Ввод:
import cv2
import numpy as np
image = cv2.imread("red_car.png")
hh, ww = image.shape[:2]
# convert to HSV
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# create a binary thresholded image
lower = (80,100,180)
upper = (255,255,255)
thresh = cv2.inRange(hsv, lower, upper)
# apply morphology
kernel = np.ones((5,5), np.uint8)
clean = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
# get external contours
contours = cv2.findContours(clean, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
area_thresh1 = 500
area_thresh2 = 1000
aspect_thresh1 = 2
aspect_thresh2 = 4
result1 = image.copy()
result2 = image.copy()
for c in contours:
# get rotated rectangle from contour
# get its dimensions
# get angle relative to horizontal from rotated rectangle
rotrect = cv2.minAreaRect(c)
box = cv2.boxPoints(rotrect)
box = np.int0(box)
(center), (dim1,dim2), angle = rotrect
maxdim = max(dim1,dim2)
mindim = min(dim1,dim2)
area = dim1 * dim2
if area > 0:
aspect = maxdim / mindim
#print(area, aspect)
if area > area_thresh1 and area < area_thresh2 and aspect > aspect_thresh1 and aspect < aspect_thresh2:
# draw contour on input
cv2.drawContours(result1,[c],0,(255,255,255),1)
# draw rectangle on input
cv2.drawContours(result2,[box],0,(255,255,255),1)
print(area, aspect)
# save result
cv2.imwrite("red_car_thresh.png",thresh)
cv2.imwrite("red_car_clean.png",clean)
cv2.imwrite("red_car_thresh_result1.png",result1)
cv2.imwrite("red_car_thresh_result2.png",result2)
# display result
cv2.imshow("thresh", thresh)
cv2.imshow("clean", clean)
cv2.imshow("result1", result1)
cv2.imshow("result2", result2)
cv2.waitKey(0)
cv2.destroyAllWindows()
Пороговое изображение:
Изображение, очищенное от морфологии:
Контур автомобиля:
Ограничивающая рамка с поворотом автомобиля:
Комментарии:
1. Спасибо, что это действительно работает. Однако, когда я тестировал это на видео, он не обнаруживает автомобиль с меткой времени cetrain. Я думаю, мне нужно настроить среднюю площадь и соотношение автомобилей во всем видео, чтобы заставить его работать. Был бы благодарен за голосование 🙂
2. Да, настройте пороговые значения по мере необходимости для масштаба изображений и типов транспортных средств.
Ответ №2:
Сопоставление шаблона с несколькими управляющими параметрами, такими как (размер .. и т.д.), Может работать для вашего случая :
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('Path_To_\target.jpg',0)
img2 = img.copy()
imgDisp = cv2.cvtColor(img2 , cv2.COLOR_GRAY2RGB)
template = cv2.imread('Path_t0\template.jpg',0)
w, h = template.shape[::-1]
# All the 6 methods for comparison in a list
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR',
'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']
for meth in methods:
img = img2.copy()
method = eval(meth)
# Apply template Matching
res = cv2.matchTemplate(img,template,method)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
# If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum
if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
top_left = min_loc
else:
top_left = max_loc
bottom_right = (top_left[0] w, top_left[1] h)
cv2.rectangle(imgDisp,top_left, bottom_right, 255, 2)
plt.subplot(121),plt.imshow(res,cmap = 'gray')
plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(imgDisp,cmap = 'gray')
plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
plt.suptitle(meth)
plt.show()
Результат :
Вы можете доработать код ЗДЕСЬ
Комментарии:
1. Спасибо за ответ. Я уже пробовал сопоставлять шаблоны раньше. на самом деле i не работает хорошо, поскольку обнаруживает несколько областей, которые не имеют отношения к целевому объекту (транспортному средству). К вашему сведению, я работаю над видеокадрами, а не над неподвижным изображением. @Ziri