随便:高空抛物、动物检测(opecv运动物体检测)

该博客介绍了如何使用OpenCV库实现实时视频流中的运动物体检测。通过帧差法、二值化、膨胀腐蚀等图像处理技术检测运动物体,并在检测到动物入侵时触发事件告警,保存图像并发送消息。同时,代码示例展示了如何结合ZMQ进行发布订阅通信。
摘要由CSDN通过智能技术生成

项目场景:对于高空抛物、在无人仓库内检测是否有动物入侵。、

实现需求:检测到事件发出事件告警,标出物体坐标和图片。

附上源码一份:

#include"opencv2/opencv.hpp"  
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
#include <iostream>  
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <zmq.h>

#define NUM 200  // images save max num
using namespace std;
string path = "/home/nvidia/Desktop/Veolia/animalRecognize2/imgs/";

void saveImg(string& savePath, Mat &frame);
//运动物体检测函数声明  
Mat MoveDetect(int &flag, Mat temp, Mat frame);
 
int main(int argcs, char** argvs)
{
	/*------------------------*/
	// create publisher
    char tcp[100] = "tcp://*:";
    strcat(tcp,argvs[2]);
    printf("tcp:%s\n",tcp);
    void *context = zmq_ctx_new();
    // create publisher
    void *publisher = zmq_socket(context, ZMQ_PUB);
    // bind pub to localhost 
    // int ret = zmq_bind(publisher, "tcp://*:5555");
    int ret = zmq_bind(publisher, tcp);
    assert(ret == 0);
	printf("publisher created!\n");
	/*------------------------*/

	//读取帧、平滑、帧差或背景差、二值化、膨胀、腐蚀。

	VideoCapture video(argvs[1]);
	if (!video.isOpened())
		return -1;

	int i = 0;
	//int frameCount = video.get(CAP_PROP_FRAME_COUNT);//获取帧数  
	double FPS = video.get(CAP_PROP_FPS);//获取FPS  
	int interval = 1000.0 / FPS;
	Mat frame;//存储帧  
	Mat temp;//存储前一帧图像  
	Mat result;//存储结果图像
	int frameCount = 0;  
	int flag = 0;  //index wether detect movement

	while (video.isOpened())
	{
		// for (int i = 0; i < frameCount; i++)
		// {
		
		//读取帧
		video >> frame;//读帧进frame
		// jump one frame
		frameCount ++;
		if(frameCount>10000) frameCount=1;
		if ((frameCount % 3) != 0) continue;
		//if(i%2)continue;
		if (frame.empty())//对帧进行异常检测  
		{
			cout << "frame is empty!" << endl;
			while(1){
				VideoCapture video(argvs[1]);
				video >> frame;
				if (!video.isOpened())return -1;
				if(!frame.empty())break;
			}
		}
		// resize
		Size dsize = Size(800, 600);
		resize(frame, frame, dsize, INTER_LINEAR);
		// cout<<"w: "<<frame.cols<<", h: "<<frame.rows<<endl;
		//处理帧
		flag = 0;
		if (i == 0)//如果为第一帧(temp还为空)  
		{
			//cout<<"first frame "<<endl;
			//调用MoveDetect()进行运动物体检测,返回值存入result 
			result = MoveDetect(flag, frame, frame);
		}
		else//若不是第一帧(temp有值了)  
		{
			//cout<<"frame id : "<<i<<endl;
			result = MoveDetect(flag, temp, frame);//调用MoveDetect()进行运动物体检测,返回值存入result
			// cout<<"i: "<<i<<endl;
		}

		imshow("result", result);
        /*-------------------------*/
		if (flag == 1){

			int n = i%NUM;
    		string savePath = path + to_string(n) + ".jpg";
			saveImg(savePath, result);
			// send msg
			// msg.trigger = flag;
			// msg.address = savePath;
			char send_buf[256];
			sprintf(send_buf, "community:%s;type:animal;cameraid:%s;url:%s;imageUrl:",argvs[3], argvs[4],argvs[1]);
			strcat(send_buf,savePath.c_str());
			cout << send_buf << endl;
			int ret = zmq_send(publisher, send_buf, strlen(send_buf)+1, 0);

		}
        
		if (waitKey(interval) == 27)//按原FPS显示  
		{
			cout << "ESC退出!" << endl;
			break;
		}
		// temp = frame.clone();
		temp = frame;
		// imshow("temp", temp);
		i++;
		if (i>1000) i=1;
		// }
	}
	destroyAllWindows();

	zmq_close(publisher);
    zmq_ctx_destroy(context);

	return 0;
 
}


Mat MoveDetect(int &flag, Mat temp, Mat frame)
{

	//平滑、帧差或背景差、二值化、膨胀、腐蚀。
	Mat result = frame.clone();
 
	//将background和frame转为灰度图  
	Mat gray1, gray2;
	
	cvtColor(temp, gray1, COLOR_BGR2GRAY);
	
	cvtColor(frame, gray2, COLOR_BGR2GRAY);
	
	//将background和frame做差  
	Mat diff;
	absdiff(gray1, gray2, diff);
	//imshow("帧差图", diff);
 
 
	//对差值图diff_thresh进行阈值化处理  二值化
	Mat diff_thresh;
	Mat kernel_erode = getStructuringElement(MORPH_RECT, Size(3, 3));
	Mat kernel_dilate = getStructuringElement(MORPH_RECT, Size(18, 18));
 
	//进行二值化处理,选择50,255为阈值
	threshold(diff, diff_thresh, 50, 255, THRESH_BINARY);
	//imshow("二值化处理后", diff_thresh);
	//腐蚀  
	erode(diff_thresh, diff_thresh, kernel_erode);
	//膨胀  
	dilate(diff_thresh, diff_thresh, kernel_dilate);
	//imshow("膨胀处理后", diff_thresh);
	
	//imshow("腐蚀处理后", diff_thresh);
 
	//查找轮廓并绘制轮廓  
	vector<vector<Point> > contours;
	findContours(diff_thresh, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);//找轮廓函数
	drawContours(result, contours, -1, Scalar(0, 0, 255), 2);//在result上绘制轮廓  
	// drawContours(frame, contours, -1, Scalar(0, 0, 255), 2);//在result上绘制轮廓 
	 //查找正外接矩形  
	vector<Rect> boundRect(contours.size());
	Rect result_bbox;
	double area = 0;
	for (int i = 0; i < contours.size(); i++)
	{
		boundRect[i] = boundingRect(contours[i]);
		if(boundRect[i].width<30 || boundRect[i].height<30)continue;
		//if(boundRect[i].width*boundRect[i].height>area) result_bbox = boundRect[i];
		rectangle(result, boundRect[i], Scalar(0, 255, 0), 2);//在result上绘制正外接矩形 green
		// rectangle(frame, boundRect[i], Scalar(0, 255, 0), 2);//在result上绘制正外接矩形 green
		flag = 1; // movement detected
	}
	//rectangle(result, boundRect[i], Scalar(0, 255, 0), 2);
	return result;//返回result
}

void saveImg(string& savePath, Mat &frame){
    // int n = i%NUM;
    // string savePath = path + to_string(n) + ".jpg";

    if (access(savePath.c_str(),0) != -1){
        // cout<< "file exists" << savePath << endl;
		// delete 
		remove(savePath.c_str());
		//save
		imwrite(savePath, frame);
    }
    else{
        // cout<<"file not exist"<< savePath <<endl;
		//save
		imwrite(savePath, frame);
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值