import cv2 import numpy as np # type: ignore import pandas as pd # type: ignore import imutils from backend.utils import timeit DELTA_THRESH = 10 MIN_AREA = 4000 class Detector(): """Class motion detector""" @timeit def __init__(self): self.avg = None self.colors = np.random.uniform(0, 255, size=(100, 3)) @timeit def prediction(self, image): image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) image = cv2.GaussianBlur(image, (21, 21), 0) if self.avg is None: self.avg = image.copy().astype(float) cv2.accumulateWeighted(image, self.avg, 0.5) frameDelta = cv2.absdiff(image, cv2.convertScaleAbs(self.avg)) thresh = cv2.threshold( frameDelta, DELTA_THRESH, 255, cv2.THRESH_BINARY)[1] thresh = cv2.dilate(thresh, None, iterations=2) cnts = cv2.findContours( thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) self.avg = image.copy().astype(float) return cnts @timeit def filter_prediction(self, output, image): if len(output) < 2: return pd.DataFrame() else: df = pd.DataFrame(output) df = df.assign( area=lambda x: df[0].apply(lambda x: cv2.contourArea(x)), bounding=lambda x: df[0].apply(lambda x: cv2.boundingRect(x)) ) df = df[df['area'] > MIN_AREA] df_filtered = pd.DataFrame( df['bounding'].values.tolist(), columns=['x1', 'y1', 'w', 'h']) df_filtered = df_filtered.assign( x1=lambda x: x['x1'].clip(0), y1=lambda x: x['y1'].clip(0), x2=lambda x: (x['x1'] + x['w']), y2=lambda x: (x['y1'] + x['h']), label=lambda x: x.index.astype(str), class_name=lambda x: x.index.astype(str), ) return df_filtered def draw_boxes(self, image, df): for idx, box in df.iterrows(): color = self.colors[int(box['label'])] cv2.rectangle(image, (box['x1'], box['y1']), (box['x2'], box['y2']), color, 6) cv2.putText(image, box['label'], (box['x1'], box['y1'] - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2) return image if __name__ == "__main__": image = cv2.imread("./imgs/image.jpeg") print(image.shape) detector = Detector() image2 = cv2.imread("./imgs/image_box.jpg") print(image2.shape) image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY) image2 = cv2.GaussianBlur(image2, (21, 21), 0) detector.avg = image2.astype(float) output = detector.prediction(image) df = detector.filter_prediction(output, image) print(df) image = detector.draw_boxes(image, df) cv2.imwrite("./imgs/outputcv.jpg", image)