it-swarm.com.ru

Как я могу обнаружить объект в кадре изображения с помощью OpenCV?

Я разрабатываю ровер, используя Raspberry Pi, который подметает комнату и подбирает предметы, упавшие на землю. Для обнаружения объекта я использую эталонное изображение, которое берется прямо в начале работы ровера, и изображение (новое изображение), которое нажимается каждые 10 секунд. Чтобы определить, есть ли изменение в кадре изображения, я делаю вычитание изображения между опорным изображением и новым изображением. Если какое-либо различие будет найдено, оно нарисует контур вокруг него, а если площадь контура превышает определенный порог (предупреждающий шаг), он заключает, что объект существует. 

Я использую следующий код -

import numpy as np
import cv2,time

img=cv2.imread("object1.jpg")
img1=cv2.imread("object2.jpg")
sub=cv2.subtract(img,img1)

gray=cv2.cvtColor(sub,cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray,(3,3),0)
_, contours, _= cv2.findContours(blur,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
c=max(contours,key=cv2.contourArea)
print(cv2.contourArea(c))

if cv2.contourArea>20000:
   print("Object detected !")

Приведенный выше код использует только 2 изображения для расчета их разницы и определения наличия объекта. Обратите внимание, что я не разместил здесь исходный код, который я буду использовать в своем проекте.

Теперь вышеприведенный код прекрасно работает для очень контролируемых ситуаций, например, когда фон изображения очень постоянный или в нем нет тени. Но учитывая тот факт, что ровер будет перемещаться по комнате, и есть вероятность, что изменения освещения могут вызвать обнаружение ложного объекта, даже если в кадре нет реального объекта. Разница может быть вызвана из-за ложных контуров от эффектов тени. 

Я хочу знать, есть ли какой-либо другой способ достижения этого обнаружения объекта без вычитания переднего плана/фонового изображения. Я также рассмотрел возможность использования ультразвукового датчика для обнаружения присутствия объекта, однако это не очень надежный вариант. Я бы предпочел решение на основе обработки изображений.

Спасибо .

================================================== ========================

Правка 1 - 

Итак, я решил немного изменить алгоритм. Я выполнил настройку порога как на переднем, так и на фоновом изображениях, а затем выполнил абсдифф между двоичными изображениями, чтобы получить любое изменение кадра (объекта). Код выглядит следующим образом - 

import numpy as np
import cv2,time

img1=cv2.imread("back.jpeg")
blur1 = cv2.GaussianBlur(img1,(5,5),0)
gray1=cv2.cvtColor(blur1,cv2.COLOR_BGR2GRAY)
ret,thresh1 = cv2.threshold(gray1,65,255,cv2.THRESH_BINARY_INV)

img2=cv2.imread("front.jpeg")
blur2 = cv2.GaussianBlur(img2,(5,5),0)
gray2=cv2.cvtColor(blur2,cv2.COLOR_BGR2GRAY)
ret,thresh2 = cv2.threshold(gray2,65,255,cv2.THRESH_BINARY_INV)

diff=cv2.absdiff(thresh2,thresh1)
diff=cv2.bitwise_xor(diff,thresh1)

kernel = np.ones((2,2),np.uint8)
diff=cv2.erode(diff,kernel,iterations = 1)
diff=cv2.dilate(diff,kernel,iterations = 8)

_, contours, _= cv2.findContours(diff,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
c=max(contours,key=cv2.contourArea)
x,y,w,h = cv2.boundingRect(c)
cv2.rectangle(diff,(x,y),(x+w,y+h),(125,125,125),2)


cv2.imshow("thresh",diff)
cv2.waitKey(0)

«Абдифф» сопровождается эрозией и дилатацией. После этого я нахожу самый большой контур и определяю, есть ли объект. Изображения, используемые в алгоритме, следующие:

  1. Фоновое изображение - Фоновое изображение

  2. Изображение переднего плана - Изображение переднего плана

  3. Порог переднего плана - Порог переднего плана Изображение

  4. Фоновый порог - Фоновый порог Изображение

  5. Разностное изображение - Окончательное изображение с контуром и его границей.

Как видите, обнаружение работает нормально. У меня есть несколько других изображений переднего плана, которые я использовал для проверки алгоритма. Они дали удовлетворительные результаты. Я хотел бы знать, есть ли другой способ достижения того же результата с большей эффективностью.

PS- Все изображения переднего плана были сделаны с помощью Flash ON. Я пробовал с выключенной вспышкой, но на изображении, кажется, много шума.

================================================== ===========

Правка 2-

Производительность алгоритма с использованием других картинок - 

Примечание: - Фоновое изображение осталось прежним.

  1. Объект 1 - Изображение переднего плана 1
  2. Обнаружение объекта 1 - Изображение переднего плана 1 Результат
2
Boudhayan Dev

Я сомневаюсь, что если эта проблема настолько проста, как вы описали в этом вопросе, она станет очень сложной, когда мы перейдем к сценарию реального мира.

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

Вот реализация Python для того же:

img = cv2.imread('D:/Image/objects.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# binarize the image
ret, bw = cv2.threshold(gray, 128, 255, 
cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

# find connected components
connectivity = 4
nb_components, output, stats, centroids = 
cv2.connectedComponentsWithStats(bw, connectivity, cv2.CV_32S)
sizes = stats[1:, -1]; nb_components = nb_components - 1
min_size = 250 #threshhold value for objects in scene
img2 = np.zeros((img.shape), np.uint8)
for i in range(0, nb_components+1):
    # use if sizes[i] >= min_size: to identify your objects
    color = np.random.randint(255,size=3)
    # draw the bounding rectangele around each object
    cv2.rectangle(img2, (stats[i][0],stats[i][1]),(stats[i][0]+stats[i][2],stats[i][1]+stats[i][3]), (0,255,0), 2)
    img2[output == i + 1] = color

Изображение, содержащее объекты:

 Original Image

Обнаруженные объекты с использованием меток подключенных компонентов:

 CNN image

3
flamelite

Другой подход, который вы можете рассмотреть, - это использовать структуру из движения, реконструировать среду/облако точек, и кластер точек над поверхностью пола принадлежит вашему объекту. Также можно комбинировать это с вашим методом вычитания фона, чтобы удалить ложное обнаружение, например тени, которые вызывают проблемы для этого метода.

0
fireant