对于一些图像的基本操作,总是需要百度,用一个完整的例程记录一下这些基本操作。
#include <opencv2/core/core.hpp>
#include <opencv2/ml/ml.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/aruco.hpp>
#include <opencv2/imgproc/imgproc.hpp>
void detect(cv::Mat &_img){
//Mat imgHSV;
//cvtColor(_img, imgHSV, COLOR_BGR2HSV);
cv::Mat imgThresholded, imgThresholded1, imgThresholded2;
cv::Mat binaImg;
//转成灰度图像,再进行二值化滤波
cv::imshow("imgThresholded1", B);
cv::threshold(binaImg, _img, THRESH_BINARY);
cv::threshold(binaImg, _img, 200, 255, THRESH_BINARY_INV);
cv::imshow("binaImg", _img);
//HSV滤波 过滤白色 ParamPrep是整个项目的一个结构体,就是一个参数模块化的作用
ParamPrep paramPrep1 = ParamPrep(ParamHSV(Scalar(0, 0, 199), Scalar(35, 6, 255)), ParamMorph(2));
ParamPrep paramPrep2 = ParamPrep(ParamHSV(Scalar(0, 0, 199), Scalar(35, 6, 255)), ParamMorph(5));
cvtColor(A, imgThresholded1, COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV
cv::inRange(imgThresholded1, paramPrep2.pHSV.scalarL, paramPrep2.pHSV.scalarH, imgThresholded2); //Threshold the image 把imgThresholded1二值化为imgThresholded2
//cv::imshow("imgThresholded1", imgThresholded1);
//cv::waitKey(0);
//形态学处理,开闭运算,开运算去除噪声,闭运算填补小洞
if (paramPrep2.usingMorph == true) {
int _size1 = paramPrep1.pMorph.opSize;
int _size2 = paramPrep2.pMorph.clSzie;
Mat element1 = getStructuringElement(paramPrep2.pMorph.shape, Size(_size1, _size1));
Mat element2 = getStructuringElement(paramPrep2.pMorph.shape, Size(_size2, _size2));
//开闭运算提供不同的核
if (paramPrep2.pMorph.openOp)
morphologyEx(imgThresholded2, imgThresholded2, MORPH_OPEN, element1);
if (paramPrep2.pMorph.closeOp)
morphologyEx(imgThresholded2, imgThresholded2, MORPH_CLOSE, element2);
}
cv::imshow("imgThresholded2", imgThresholded2);
//cv::waitKey(0);
//imgThresholded = imgThresholded1 | imgThresholded2;
//Mat =操作浅拷贝
//深拷贝 1) img.copyTo(img1) 2) img1=img.clone()
imgThresholded = imgThresholded2;
//找contour,这个一个点集合
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
findContours(imgThresholded, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE, cv::Point());
//外接矩形
cv::Rect fRect = cv::Rect(0, 0, 0, 0);
cv::Rect rect = cv::Rect(0, 0, 0, 0);
cv::Mat imageContours = cv::Mat::zeros(imgThresholded.size(), CV_32FC3); //最小外接矩形画布
for (int i = 0; i < contours.size(); i++)
{
cv::Rect tRect = cv::Rect(0, 0, 0, 0);
//cv::Rect lRect = cv::Rect(0, 0, 0, 0);
int tarea;
int farea;
//获取boundingbox
tRect = cv::boundingRect(contours[i]);
tarea = tRect.area();
//判断面积
if (tarea < 2000) continue;
//合并矩形
rect = fRect | tRect;
fRect = cv::Rect(rect);
//把矩形画出来看看
cv::rectangle(imageContours, rect, Scalar(0, 0, 255), 2, 8, 0);
}
//在原图上画,和在画布上面看
cv::rectangle(imageContours, rect, Scalar(0, 255, 0), 2, 8, 0);
cv::rectangle(_img, rect, Scalar(0, 255, 0), 2, 8, 0);
cv::imshow("contours", imageContours);
//把获取的二维码区域裁剪出来进行二次滤波,为了获取boungidngbox
cv::Mat secondImg = imgThresholded1(rect);
ParamPrep paramPrep3 = ParamPrep(ParamHSV(Scalar(0, 0, 0), Scalar(61, 255, 141)), ParamMorph(2));
cv::inRange(secondImg, paramPrep3.pHSV.scalarL, paramPrep3.pHSV.scalarH, secondImg); //Threshold the image
//cv::imshow("secondImg", secondImg);
//cv::imshow("secondImg2", secondImg);
std::vector<std::vector<cv::Point>> contours1;
std::vector<cv::Vec4i> hierarchy1;
findContours(secondImg, contours1, hierarchy1, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE, cv::Point());
//外接矩形
//cv::Rect wantRect;
cv::Rect sRect = cv::Rect(0, 0, 0, 0);
cv::Rect sfRect = cv::Rect(0, 0, 0, 0);
cv::Mat imageContours1 = cv::Mat::zeros(secondImg.size(), CV_32FC3); //最小外接矩形画布
cout <<" contours1.size()"<< contours1.size() << endl;
//遍历contours
for (int i = 0; i < contours1.size(); i++)
{
cv::Rect stRect = cv::Rect(0, 0, 0, 0);
int sfarea;
stRect = cv::boundingRect(contours1[i]);
if (stRect.area() < 2000) continue;
sRect = sfRect | stRect;
sfRect = cv::Rect(sRect);
cv::rectangle(imageContours1, sRect, Scalar(0, 0, 255), 2, 8, 0);
cv::imshow("imageContours1", imageContours1);
}
cout << "zzzzz" << sRect.x+rect.x << " " << sRect.y+ rect.y << endl;
//在二值化图像上画图,一个量就够了
cv::rectangle(secondImg, sRect, 200, 2, 8, 0);
cv::imshow("secondImg", secondImg);
}