我是图像处理新手,我有点挣扎,我正在制作自己的 DIY 安全软件,并且我做了一个功能来检测某些运动,以便开始录制并通知我。
这个函数的想法是拍摄两个图像并比较它们以找到一些运动,我遇到的问题是:
我尝试选项2的方式是通过注释代码,主要思想是
这是我的代码:
import cv2
import numpy as np
from skimage.metrics import structural_similarity as ssim
def count_diff_nb(img_1, img_2):
# resize images
img_1_height, img_1_width = img_1.shape[:2]
new_height = int((600 / img_1_width) * img_1_height)
img_1 = cv2.resize(img_1, (600,new_height))
img_2 = cv2.resize(img_2, (600,new_height))
# convert to gray scale
gray_image1 = cv2.cvtColor(img_1, cv2.COLOR_BGR2GRAY)
gray_image2 = cv2.cvtColor(img_2, cv2.COLOR_BGR2GRAY)
# Gaussian blur in order to remove some noise
blur1 = cv2.GaussianBlur(gray_image1, (5,5), 0)
blur2 = cv2.GaussianBlur(gray_image2, (5,5), 0)
# divide (bad idea)
#divide1 = cv2.divide(gray_image1, blur1, scale=255)
#divide2 = cv2.divide(gray_image2, blur2, scale=255)
# Compute SSIM between two images
#ssim_value, diff = ssim(gray_image1, gray_image2, full=True)
ssim_value, diff = ssim(blur1, blur2, full=True)
#ssim_value, diff = ssim(divide1, divide2, full=True)
diff_percent = (1 - ssim_value) * 100
# The diff image contains the actual image differences between the two images
# and is represented as a floating point data type so we must convert the array
# to 8-bit unsigned integers in the range [0,255] before we can use it with OpenCV
diff = (diff * 255).astype("uint8")
# Adaptative threshold (bad idea too)
#thresh = cv2.adaptiveThreshold(diff, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)
#thresh = cv2.adaptiveThreshold(diff, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 3, 10)
# Threshold the difference image
thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
# followed by finding contours to
# obtain the regions that differ between the two images
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
# Highlight differences
mask = np.zeros(img_1.shape, dtype='uint8')
filled = img_2.copy()
contours_nb = 0
for c in contours:
# limit is an area so sqrt of size
area = cv2.contourArea(c)
# 72000 is 1/3 of global img area
if area > 2000 and area < 72000:
contours_nb = contours_nb + 1
x,y,w,h = cv2.boundingRect(c)
cv2.rectangle(img_1, (x, y), (x + w, y + h), (36,255,12), 2)
cv2.rectangle(img_2, (x, y), (x + w, y + h), (36,255,12), 2)
cv2.drawContours(mask, [c], 0, (0,255,0), -1)
cv2.drawContours(filled, [c], 0, (0,255,0), -1)
return contours_nb, diff_percent, img_2, filled
为了能够找到灵敏度(不是错过检测)和忽略由于黑暗而产生的随机噪声之间的最佳点,你有什么想法或我缺少的东西吗?
我想在转换为灰度之前忽略深色,但如果移动的东西是黑色的……我认为这是一个坏主意。
非常感谢!
我不知道你做错了什么,但谷歌搜索一下你可以找到很多方法,例如从使用轮廓检测和背景减法使用OpenCV进行移动物体检测,你可以找到一个很好的流程图使用 OpenCV 的对象检测管道 :
提到了背景减法,在你的算法中没有描述,但我可能是错的,我无法通过地球读取opencv。在文档中,他们将其中一种方法描述为:
它使用前几帧(默认为 120)进行背景建模。 它采用概率前景分割算法,使用贝叶斯推理来识别可能的前景对象。估计是自适应的;新的观测值比旧的观测值具有更大的权重,以适应可变的照明。进行一些形态过滤操作(例如关闭和打开)以消除不需要的噪声。在前几帧中您将看到一个黑色窗口......
你实际上可以在 OpenCV 文档上找到它 :
显然有两个BackgroundSubtractorMOG和BackgroundSubtractorGMG。这意味着流的第一帧应该作为运动检测的基线。我不知道您是否需要重新校准您的设置,以防您正在对 24 小时运行的安全摄像头进行编程,并遇到大量环境光线变化