代码
// win10
// vs2013
// opencv3
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
// 图像差分法
int main()
{
Mat image = imread("image.jpg");
Mat test = imread("test.jpg");
Mat dframe;
namedWindow("image");
namedWindow("test");
namedWindow("dframe");
// 帧间差分
// 计算两幅图像各个通道的相对应元素的差的绝对值
absdiff(test, image, dframe);
threshold(dframe, dframe, 70, 255, CV_THRESH_TOZERO);
imshow("image", image);
imshow("test", test);
imshow("dframe", dframe);
int n = 1;
char diff[20];
sprintf(diff, "diff//%d.jpg",n);
//将差分图像存入文件夹
imwrite(diff, dframe);
waitKey();
return 0;
}
效果图
获取差分值及其矩形框位置
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
//图像差分法
int main()
{
Mat image = imread("image.jpg");
Mat test = imread("test.jpg");
Mat diff;
namedWindow("image");
namedWindow("test");
namedWindow("diff");
//帧间差分
//计算两幅图像各个通道的相对应元素的差的绝对值
absdiff(test, image, diff);
threshold(diff, diff, 70, 255, CV_THRESH_TOZERO);
imshow("image", image);
imshow("test", test);
imshow("diff", diff);
//灰度化与二值化
Mat diffGray, diffBi;
cvtColor(diff, diffGray, CV_BGR2GRAY);
namedWindow("[2]灰度化");
imshow("[2]灰度化", diffGray);
threshold(diffGray, diffBi, 50, 255, CV_THRESH_BINARY);
namedWindow("[3]二值化");
imshow("[3]二值化", diffBi);
//膨胀
Mat diffSwell;
int g_nStructElementSize = 3; //结构元素(内核矩阵)的尺寸
Mat element = getStructuringElement(MORPH_RECT, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1), Point(g_nStructElementSize, g_nStructElementSize));
dilate(diffBi, diffSwell, element);
namedWindow("[5]膨胀");
imshow("[5]膨胀", diffSwell);
//外接矩形
vector<vector<Point>> contours;
vector<Vec4i> hierarcy;
findContours(diffSwell, contours, hierarcy, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE); //查找轮廓
Mat dst;
dst = Mat::zeros(diffSwell.size(), CV_8UC3);
vector<Rect> boundRect(contours.size()); //定义外接矩形集合
int x0 = 0, y0 = 0, w0 = 0, h0 = 0, num = 0;
for (int i = 0; i<contours.size(); i++)
{
boundRect[i] = boundingRect((Mat)contours[i]); //查找每个轮廓的外接矩形
drawContours(dst, contours, i, Scalar(0, 0, 255), 2, 8); //绘制轮廓
x0 = boundRect[i].x;
y0 = boundRect[i].y;
w0 = boundRect[i].width;
h0 = boundRect[i].height;
if (w0 > 0 && h0 > 0)//筛选
{
rectangle(dst, Point(x0, y0), Point(x0 + w0, y0 + h0), Scalar(0, 255, 0), 2, 8); //绘制第i个外接矩形
num++;
//输出diff位置
cout << "第" << num << "个差分值:" << endl;
cout << "起点位置:(" << x0 << "," << y0 << ")" << endl;
cout << "宽:" << w0 << " , " << "高:" << h0 << endl;
cout << endl;
//抠图
//取出目标所在矩形区域生成新图像
Rect rect(x0, y0, w0, h0);
Mat ROI = test(rect);
char f[20];
sprintf(f, "ob%d.jpg", num);
string str(f);
dilate(ROI, ROI, element);
imwrite(str, ROI);
}
}
namedWindow("[4]轮廓图");
imshow("[4]轮廓图", dst);
if (num > 0)
{
for (int i = 1; i <= num; i++)
{
char f[20];
sprintf(f, "ob%d.jpg", i);
string str(f);
Mat ob = imread(str);
namedWindow(str);
imshow(str, ob);
}
}
cout << "共有" << num << "个差分值" << endl;
waitKey();
return 0;
}
获取轮廓内所有点
参考:https://blog.csdn.net/qq_37390630/article/details/70174438?fps=1&locationNum=10&spm=1018.2118.3001.4187
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
//图像差分法
int main()
{
Mat image = imread("image.jpg");
Mat test = imread("test.jpg");
Mat diff;
namedWindow("image");
namedWindow("test");
namedWindow("diff");
//帧间差分
//计算两幅图像各个通道的相对应元素的差的绝对值
absdiff(test, image, diff);
threshold(diff, diff, 70, 255, CV_THRESH_TOZERO);
imshow("image", image);
imshow("test", test);
imshow("diff", diff);
//灰度化与二值化
Mat diffGray, diffBi;
cvtColor(diff, diffGray, CV_BGR2GRAY);
namedWindow("[2]灰度化");
imshow("[2]灰度化", diffGray);
threshold(diffGray, diffBi, 50, 255, CV_THRESH_BINARY);
namedWindow("[3]二值化");
imshow("[3]二值化", diffBi);
//膨胀
Mat diffSwell;
int g_nStructElementSize = 3; //结构元素(内核矩阵)的尺寸
Mat element = getStructuringElement(MORPH_RECT, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1), Point(g_nStructElementSize, g_nStructElementSize));
dilate(diffBi, diffSwell, element);
namedWindow("[5]膨胀");
imshow("[5]膨胀", diffSwell);
//外接矩形
vector<vector<Point>> contours;
vector<Vec4i> hierarcy;
findContours(diffSwell, contours, hierarcy, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE); //查找轮廓
cout << "轮廓总个数:" << contours.size() << endl;
vector<vector<Point>> ::const_iterator itContours = contours.begin();
for (; itContours != contours.end(); ++itContours)
cout << "轮廓包含的点数:" << itContours->size() << endl;
Mat dst;
dst = Mat::zeros(diffSwell.size(), CV_8UC3);
//vector<Rect> boundRect(contours.size()); //定义外接矩形集合
//int x0 = 0, y0 = 0, w0 = 0, h0 = 0, num = 0;
for (int i = 0; i < contours.size(); i++)
{
Scalar color = Scalar(255, 255, 255);
drawContours(dst, contours, i, color, 1, 8, hierarcy, 0, Point());
printf("\n输出轮廓序号,第%d个轮廓: \n", i);
cout << "输出轮廓包含点的总数: " << contours[i].size() << endl; //试试看输出该轮廓点的总数
// 下面三行来自http://www.opencv.org.cn/forum.php?mod=viewthread&tid=38297&page=4
// contours[i][0]表示第i个轮廓第0个点
cout << "输出轮廓第0个点的坐标 " << contours[i][0] << endl; //试试看输出轮廓第一个点的坐标 x,y
cout<< "输出轮廓第0个点的x坐标 " << contours[i][0].x << endl; //试试看输出轮廓第一个点的横坐标 x
cout<< "输出轮廓第0个点的y坐标 " << contours[i][0].y << endl; //试试看输出轮廓第一个点的纵坐标 y
}
namedWindow("[4]轮廓图");
imshow("[4]轮廓图", dst);
waitKey();
return 0;
}