2.在数字图像处理里面,每张图像都被看成一个三维的矩阵,那么把两张图像矩阵一相减,就得到差异的地方,在OpenCV库里面有封装的函数subtract()可以实现为个功能。这个API也可用来做差分法运动跟踪。
3.我这里的编程环境是Windows 10 64位,IDE是VS2019,配置了OpenCV 4.5,实现语言是C++。
1.创建新的工程,把编译好的OpenCV导入到Vs里,添加系统环境。
2.实现代码
#include
#include
#include
void imshow(std::string name, const cv::Mat& cv_src)
{
cv::namedWindow(name, 0);
int max_rows = 800;
int max_cols = 800;
if (cv_src.rows >= cv_src.cols && cv_src.rows > max_rows)
{
cv::resizeWindow(name, cv::Size(cv_src.cols * max_rows / cv_src.rows, max_rows));
}
else if (cv_src.cols >= cv_src.rows && cv_src.cols > max_cols)
{
cv::resizeWindow(name, cv::Size(max_cols, cv_src.rows * max_cols / cv_src.cols));
}
cv::imshow(name, cv_src);
}
void imageSubtract(const cv::Mat& image1, const cv::Mat& image2,cv::Mat &cv_dst)
{
if (image1.empty() || image2.empty())
{
return;
}
cv::Mat cv_src1 = image1.clone();
cv::Mat cv_src2 = image2.clone();
if ((image1.rows != image2.rows) || (image1.cols != image2.cols))
{
int rows = (image1.rows + image2.rows) / 2;
int cols = (image1.cols + image2.cols) / 2;
cv::resize(image1, cv_src1, cv::Size(cols, rows));
cv::resize(image2, cv_src2, cv::Size(cols, rows));
}
cv::Mat image1_gary, image2_gary;
if (cv_src1.channels() != 1)
{
cvtColor(cv_src1, image1_gary, cv::COLOR_BGR2GRAY);
}
if (cv_src2.channels() != 1)
{
cvtColor(cv_src2, image2_gary, cv::COLOR_BGR2GRAY);
}
cv::Mat frameDifference, absFrameDifferece;
cv::Mat previousGrayFrame = image2_gary.clone();
//图1减图2
subtract(image1_gary, image2_gary, frameDifference, cv::Mat(), CV_16SC1);
//取绝对值
absFrameDifferece = abs(frameDifference);
//位深的改变
absFrameDifferece.convertTo(absFrameDifferece, CV_8UC1, 1, 0);
imshow("absFrameDifferece", absFrameDifferece);
cv::Mat segmentation;
//阈值处理(这一步很关键,要调好二值化的值)
threshold(absFrameDifferece, segmentation, 10, 255, cv::THRESH_BINARY);
//threshold(absFrameDifferece, segmentation, 0, 255, cv::THRESH_OTSU);
imshow("bin", segmentation);
//形态学处理(开闭运算)
//形态学处理用到的算子
cv::Mat morphologyKernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5), cv::Point(-1, -1));
morphologyEx(segmentation, segmentation, cv::MORPH_CLOSE, morphologyKernel, cv::Point(-1, -1), 2, cv::BORDER_REPLICATE);
//找边界
std::vector< std::vector<cv::Point> > contours;
std::vector<cv::Vec4i> hierarchy;
findContours(segmentation, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point(0, 0));//CV_RETR_TREE
std::vector< std::vector<cv::Point> > contours_poly(contours.size());
std::vector<cv::Rect> boundRect;
cv_dst = cv_src1.clone();
for (int index = 0; index < contours.size(); index++)
{
approxPolyDP(cv::Mat(contours[index]), contours_poly[index], 3, true);
cv::Rect rect = cv::boundingRect(cv::Mat(contours_poly[index]));
rectangle(cv_dst, rect, cv::Scalar(0, 0, 255), 2);
}
}
int main()
{
//读入图像
cv::Mat cv_image1 = cv::imread("images/F1.jpg");
cv::Mat cv_image2 = cv::imread("images/F2.jpg");
cv::Mat cv_dst;
//比较图像
imageSubtract(cv_image1, cv_image2, cv_dst);
imshow("A1", cv_image1);
imshow("A2", cv_image2);
imshow("dst", cv_dst);
cv::imwrite("cv_dst.jpg", cv_dst);
cv::waitKey();
return 0;
}
3.运行效果:
4.整个工程源码以上传到CSDN:https://download.csdn.net/download/matt45m/49898214