Table of Contents
-
- main function
- Cgraphic_math.h file
- Cgraphic_math.cpp file
- GitHub download link
Main function
#include <opencv2/opencv.hpp> #include <iostream> #include "Cgraphic_math.h" using namespace std; using namespace cv; #define num 19 #define type 1 //0: in the mean way //1: in the way of median value int main() {<!-- --> VideoCapture test_video; int count = 0; // read video test_video.open("C:\Users\Tiam\Desktop\Moving_Object_Detection\video\test.avi"); \t //Read frame number and frame rate int FrameCount = test_video.get(cv::CAP_PROP_FRAME_COUNT); int fps = test_video.get(cv::CAP_PROP_FPS); //Single frame image Mat frame; Mat frame_gray; C graphic_math graphic; graphic.setAverage_num(INT_MAX); // image array Mat image[num]; Mat img; Mat img_gray; //Fill in the number of frames processed by the median graphic.setMedian_num(num); //initialization for (int i = 0; i < num; i ++ ) {<!-- --> test_video.read(img); cvtColor(img, img_gray, CV_BGR2GRAY); \t\t image[i] = img_gray. clone(); } //The median value processing gets the background graphic.images_median(image); while (count < (FrameCount-num)) //The num frames read before need to be subtracted {<!-- --> test_video.read(frame); cvtColor(frame, frame_gray, CV_BGR2GRAY); if (type == 0) {<!-- --> //Average processing to get the background graphic.images_average(frame_gray); graphic.setDifImage(frame_gray); } else {<!-- --> //The median value processing gets the background graphic.setDifImage(frame_gray); } \t\t\t \t\t//Binarization threshold(graphic.getDifImage(), graphic.getDifImage(), 50, 255, THRESH_BINARY); vector<vector<Point>> contours; // find the center findContours(graphic.getDifImage(), contours, RETR_TREE, CHAIN_APPROX_SIMPLE); for (int i = 0; i < contours. size(); i ++ ) {<!-- --> if ((contours[i]. size() > 75) & (contours[i]. size() < 150)) {<!-- --> // find area Rect roi = boundingRect(Mat(contours[i])); rectangle(frame, roi, Vec3b(0, 0, 255), 2); } } cv::imshow("video", frame); //display \t\t cv::waitKey(fps); count + + ; } destroyAllWindows(); }
Cgraphic_math.h file
#ifndef _CGRAPHIC_MATH_H #define _CGRAPHIC_MATH_H #include <opencv2/opencv.hpp> #include <iostream> #include <string.h> using namespace std; using namespace cv; /**************************************************** ************************* * @abstract Cgraphic_math class, which realizes mean or median processing of multi-frame images, Get the background image, and finally calculate the frame difference to realize the detection of moving objects * @author [email protected] * @since opencv3.4.4 ***************************************************** *************************/ class Graphic_math {<!-- --> private: Mat image_back; //background image Mat image_dif; //detection image int average_num; // how many frames to take an average int median_num; // how many frames to take the median public: Cgraphic_math(); //constructor ~Cgraphic_math(); //destructor Mat getImage_back(void); //Get the background image Mat getDifImage(void); //Get frame difference void setDifImage(Mat image); // frame difference calculation void images_average(Mat image); //Average processing void setAverage_num(int num); //Set average processing frame number void images_median(Mat image[]);//median processing void setMedian_num(int num); //Set the median processing frame number }; #endif
Cgraphic_math.cpp file
#include "Cgraphic_math.h" Cgraphic_math::Cgraphic_math() {<!-- --> average_num = 13; median_num = 13; } Cgraphic_math::~Cgraphic_math() {<!-- --> //delete img; } /**************************************************** ******************************* * @Function: // Get the background image * @Description: // Get the background image after mean or median processing * @Input: // void * @Output: // background image * @Return: // background image ***************************************************** *******************************/ Mat Graphic_math::getImage_back(void) {<!-- --> return image_back; } /**************************************************** ******************************* * @Function: // Calculate the frame difference image * @Description: // Use the difference between the input image and the background image processed by the median or mean value to get the frame difference * @Input: // need to do poor image * @Output: // frame difference * @Return: // void ***************************************************** *******************************/ void Cgraphic_math::setDifImage(Mat image) {<!-- --> image_dif = abs(image - image_back); } /**************************************************** ******************************* * @Function: // Average processing image * @Description: // Calculate the mean value of multiple frames of images to get the background image * @Input: // The image to be processed * @Output: // background image * @Return: // void ***************************************************** *******************************/ void Cgraphic_math::images_average(Mat image) {<!-- --> static int count = 0; float q1 = count / (count + 1.0); //weight float q2 = 1 / (count + 1.0); //cvtColor(image, image, CV_BGR2GRAY); //Grayscale //The first execution needs to initialize image_back if (count == 0) {<!-- --> image_back = image. clone(); } //calculate the mean image_back = q1 * image_back + q2 * image; count + + ; // overflow if (count >= average_num) {<!-- --> count = 0; } } /**************************************************** ******************************* * @Function: // Get the frame difference image * @Description: // Get the frame difference image * @Input: // void * @Output: // None * @Return: // frame difference image ***************************************************** *******************************/ Mat Graphic_math::getDifImage(void) {<!-- --> return image_dif; } /**************************************************** ******************************* * @Function: // Set the number of frames that need mean processing * @Description: // Set the number of image frames that need to be averaged * @Input: // frame number * @Output: // average processing frame number * @Return: // None ***************************************************** *******************************/ void Cgraphic_math::setAverage_num(int num) {<!-- --> average_num = num; } /**************************************************** ******************************* * @Function: // insertion sort algorithm * @Description: // Sort the input array * @Input: // arr: the array to be processed, n: the length of the array * @Output: // sorted array arr * @Return: // None ***************************************************** *******************************/ void InsertSort(int* arr, int n) {<!-- --> for (int i = 0; i < n - 1; + + i) {<!-- --> //Record the subscript of the last element of the ordered sequence int end = i; // element to be inserted int tem = arr[end + 1]; //Single trip while (end >= 0) {<!-- --> //Move backward if it is larger than the inserted number if (tem < arr[end]) {<!-- --> arr[end + 1] = arr[end]; end--; } // is smaller than the inserted number, jump out of the loop else {<!-- --> break; } } //tem is placed after the number smaller than the inserted number arr[end + 1] = tem; //There are two situations where the code executes to this position: //1. The element to be inserted finds the position where it should be inserted (break jumps out of the loop to this point) //2. The element to be inserted is smaller than all the elements in the current ordered sequence (here after the end of the while loop) } } /**************************************************** ******************************* * @Function: // image median processing * @Description: // Take the median value of the corresponding pixel points of various images to get the background image * @Input: // image[] image array that needs to be processed * @Output: // data_back background image * @Return: // None ***************************************************** *******************************/ void Cgraphic_math::images_median(Mat image[]) {<!-- --> int* arr = new int[median_num]; \t if (image_back.empty()) //Background image initialization {<!-- --> image_back = image[0]. clone(); } for (int i = 0; i < image[0].rows; i ++ ) {<!-- --> for (int j = 0; j < image[0].cols; j++ ) {<!-- --> for (int n = 0; n < median_num; n ++ ) {<!-- --> //Get the first address of the i-th line of the n-th image uchar* data = image[n].ptr<uchar>(i); arr[n] = (int)data[j]; if (n >= (median_num - 1)) {<!-- --> //The first address of the i line of the background image uchar* data_back = image_back.ptr<uchar>(i); InsertSort(arr, median_num); data_back[j] = (uchar)(arr[(median_num / 2)]); continue; } \t\t\t\t } } } delete[] arr; } /**************************************************** ******************************* * @Function: // Set the number of frames that need median processing * @Description: // Set the number of image frames that need to be median * @Input: // frame number * @Output: // median processing frame number * @Return: // None ***************************************************** *******************************/ void Cgraphic_math::setMedian_num(int num) {<!-- --> median_num = num; }
GitHub download link
download link