web-dev-qa-db-fra.com

Supprimer l'arrière-plan de l'image à l'aide de l'opencv Python

J'ai deux images, une avec uniquement un arrière-plan et l'autre avec un arrière-plan + objet détectable (dans mon cas, c'est une voiture). Ci-dessous les images

 enter image description here

J'essaie de supprimer le fond tel que je n'ai que voiture dans l'image résultante. Voici le code avec lequel j'essaie d'obtenir les résultats souhaités

import numpy as np
import cv2


original_image = cv2.imread('IMG1.jpg', cv2.IMREAD_COLOR)
gray_original = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY)
background_image = cv2.imread('IMG2.jpg', cv2.IMREAD_COLOR)
gray_background = cv2.cvtColor(background_image, cv2.COLOR_BGR2GRAY)

foreground = np.absolute(gray_original - gray_background)
foreground[foreground > 0] = 255

cv2.imshow('Original Image', foreground)
cv2.waitKey(0)

L’image obtenue en soustrayant les deux images est 

 enter image description here

Voici le problème. L'image résultante attendue devrait être uniquement une voiture . En outre, si vous regardez attentivement les deux images, vous verrez qu'elles ne sont pas exactement identiques, c'est-à-dire que l'appareil photo s'est déplacé un peu de manière peu. Ma question est qu'avec ces deux images, comment puis-je soustraire le fond. Je ne veux pas utiliser l’algorithme grabCut ou backgroundSubtractorMOG pour le moment, car je ne sais pas ce qui se passe à l’intérieur de ces algorithmes. 

Ce que j'essaie de faire est d'obtenir l'image suivante qui en résulte  enter image description here

Aussi, si possible, merci de me guider avec une manière générale de le faire, non seulement dans ce cas précis, c’est-à-dire que j’ai un fond dans une image et un fond + objet dans la deuxième image. Quel pourrait être le meilleur moyen de le faire? Désolé pour une si longue question.

14
muazfaiz

Le problème est que vous soustrayez des tableaux de unsigned nombres entiers de 8 bits. Cette opération peut déborder.

Démontrer

>>> import numpy as np
>>> a = np.array([[10,10]],dtype=np.uint8)
>>> b = np.array([[11,11]],dtype=np.uint8)
>>> a - b
array([[255, 255]], dtype=uint8)

Puisque vous utilisez OpenCV, le moyen le plus simple d'atteindre votre objectif consiste à utiliser cv2.absdiff() .

>>> cv2.absdiff(a,b)
array([[1, 1]], dtype=uint8)
4
Dan Mašek

Je recommande d'utiliser l'algorithme grabcut d'OpenCV. Commencez par dessiner quelques lignes au premier plan et à l’arrière-plan et continuez ainsi jusqu’à ce que votre premier plan soit suffisamment séparé de l’arrière-plan. Il est couvert ici: https://docs.opencv.org/trunk/d8/d83/tutorial_py_grabcut.html Ainsi que dans cette vidéo: https://www.youtube.com/ regarder? v = kAwxLTDDAwU

0
wordsforthewise