Opencv :二维数组实现简单的检测移动物体

运行环境

Visual Studio 2017+opencv 3.4
跟着这位大佬思路安装一路绿灯:https://blog.csdn.net/qq_41175905/article/details/80560429

功能和思路

能识别出摄像头拍到的任何移动物体,眨眼都可以捕捉到!
思路:

  1. 读取图片
  2. 图片转换成二维数组
  3. 判断30ms前后延迟前后图片每个像素是否有差异(阈值在20之间)
  4. 把大于阈值的用不同背景色标出
  5. 显示图片

Mat类转换成二维数组

我们在摄像头获取到的图片都是GBR类型的,为什么说是GBR呢,因为在Opencv里面,三个通道的排序是B、G、R
对于单通道图像:

Mat对象.at<uchar>(x,y);

x,y是图像上的坐标,返回一个uchar值

对于三通道图像(BGR图):

Mat对象.at<Vec3b>(x,y);

x,y是图像上的坐标,返回一个长度为3的uchar数组,分别代表BGR通道的像素值,Vec3b是一种类型,有时也会使用Vec3f,区别是b:uchar类型,f:float类型,我们当成int型使用
附一张API
在这里插入图片描述

  • 我们读取到Mat类型的图片,为了方便使用,把它转换为单通道的图片,像素改成(B+G+R)/3
  • 为什么说单通道方便呢,因为单通道可以直接整形,也可以用(b,g,r)给三通道图片赋值~
  • 看代码比较容易理解
void getimage(Mat m, int flag) {
	Size imgsize = m.size();
	for (int i = 0; i < m.rows; i ++) {
		for (int j = 0; j < m.cols; j ++) {
			//得出三个不同的像素值
			Vec3b bgr = m.at<Vec3b>(i, j);
			int b = bgr[0];
			int g = bgr[1];
			int r = bgr[2];
			//img1 img2分别是不同时间下的图片(30ms)
			if (flag == 1) {
				img1[i][j] = (b + g + r) / 3;
			}
			else
			{
				img2[i][j]= (b + g + r) / 3;
			}
		}
		
	}
}

判断比较

  • 首先要初始化图片背景
  • 再用两个数组的各个值相比较(像素比较),给定一个阈值偏差小于该值认为没有移动,大于就是移动了
for (int i = 0; i < frame.rows; i++) {
			
			for (int j = 0; j < frame.cols; j++) {
				
				if(abs(img1[i][j]-img2[i][j])>20){
					newImage.at<uchar>(i, j) = 0;
				//	drawFilledCircle(newImage, Point(i, j));
				}
				
			}
		}

code

有个画圆的函数,画出来有偏差,而且影响美观,就不用了,不过这个功能在其他需要画图的地方还是可以的。

#include<iostream>
#include<opencv/cv.h>
#include<opencv2/core/core.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int img1[480][640], img2[480][640];
void getimage(Mat m, int flag) {
	Size imgsize = m.size();
	for (int i = 0; i < m.rows; i ++) {
		for (int j = 0; j < m.cols; j ++) {
			//得出三个不同的像素值
			Vec3b bgr = m.at<Vec3b>(i, j);
			int b = bgr[0];
			int g = bgr[1];
			int r = bgr[2];
			//img1 img2分别是不同时间下的图片(30ms)
			if (flag == 1) {
				img1[i][j] = (b + g + r) / 3;
			}
			else
			{
				img2[i][j]= (b + g + r) / 3;
			}
		}
		
	}
}
/*画实心圆*/
void drawFilledCircle(cv::Mat img, cv::Point center) {
	int thickness = 1;
	int lineType = 8;

	cv::circle(img,
		center, //圆心定义
		2, //圆的半径
		Scalar(rand()%255, rand()%255, rand()%255),//随机颜色
		thickness,//线粗
		lineType);
}

int main() {
	VideoCapture capture(0);
	Mat frame;
	int count = 1;
	while (true) {
		capture >> frame;
		Size imgsize = frame.size();
		count = -count;
		Mat newImage = Mat(imgsize, CV_8UC1);
		
		//cout << frame.rows << " " << frame.cols;
		for (int i = 0; i < frame.rows; i++) {
			for (int j = 0; j < frame.cols; j++) {
				newImage.at<uchar>(i, j) = 255;
			}
		}
		getimage(frame, count);
		for (int i = 0; i < frame.rows; i++) {
			
			for (int j = 0; j < frame.cols; j++) {
				
				if(abs(img1[i][j]-img2[i][j])>20){
					newImage.at<uchar>(i, j) = 0;
				//	drawFilledCircle(newImage, Point(i, j));
				}
				
			}
		}
		
		if (!frame.empty()) {
			imshow("NewImage", newImage);
		}
		if (waitKey(30) == 27)
			break;
	}

}

在这里插入图片描述
我同学用=用visual studio做CV都很卡!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值