示例代码
/************************************************************************
<*@创建者:OYXL
<*@时间:2018/6/20
<*@实现功能:图片或者视频进行二值化,可选择
<*@备注:图片二值化,显示图像必须和二值响应函数放在一块,不然不会执行
<*@备注:on_Threshold( int, void* );不可更改参数
<*@修改:添加了边缘检测和绘制轮廓以及最小包围矩形功能
************************************************************************/
#include "opencv2/opencv.hpp"
#include "iostream"
using namespace std;
using namespace cv;
int Picture();
int Video();
void on_Threshold( int, void* );//回调函数
void ChooseMode();
Mat img,copyImage,gray,binary,imgThresholded;
int thr=100;
int num=0;
int BinaryType=2;
vector<vector<Point>> contours;
vector<Vec4i> Hierarchy;
int main()
{
ChooseMode();
if (num==1)
{
Picture();
}
else if (num==2)
{
Video();
}
return 0;
}
//<图片二值化函数
int Picture()
{
namedWindow("TrackBar", CV_WINDOW_AUTOSIZE); //create a window called "Control"
createTrackbar("THR", "TrackBar", &thr, 255,on_Threshold); //Hue (0 - 180)
img=imread("F:\\磊神图片\\9527.png");
img.copyTo(copyImage);
if (!img.data)
{
cout << "picture failed to load !" << endl;
return -1;
}
cvtColor(img, gray, CV_BGR2GRAY);//<必须先进行二值化操作,不然得到的二值图是彩色的
GaussianBlur(gray, gray, Size(15, 15), 0, 0);
on_Threshold(0,0);
//threshold(gray, binary, thr, 255, 4);
waitKey(0);
}
//<视频二值化函数
int Video()
{
namedWindow("TrackBar", CV_WINDOW_AUTOSIZE); //create a window called "Control"
createTrackbar("THR", "TrackBar", &thr, 255,0); //Hue (0 - 180)
VideoCapture capture("F:\\磊神视频\\noglasses.avi");
while (true)
{
capture >> img;
if (img.empty()) //判断摄像头是否打开
{
cout << "Video failed to load !" << endl;
return -1;
}
cvtColor(img, gray, CV_BGR2GRAY);
GaussianBlur(gray, gray, Size(15, 15), 0, 0);
threshold(gray, binary, thr, 255, BinaryType);
Canny(binary,imgThresholded,3,9,3);
findContours(imgThresholded,contours,Hierarchy,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE,Point(0,0));
vector<RotatedRect> box(contours.size());
Point2f vertex[4];
if(contours.size()>0)
{
for (int i=0;i<contours.size();i++)
{
box[i]=minAreaRect(Mat(contours[i]));
box[i].points(vertex);
drawContours(img,contours,i,Scalar(0,0,255),2,8,Hierarchy,0,Point(0,0));
for (int j=0;j<4;j++)
{
line(img,vertex[j],vertex[(j+1)%4],Scalar(255,0,255),2,CV_AA);
}
}
}
imshow("src", img);
imshow("binary image", binary);
waitKey(1);
}
}
/************************************************************************
<*@阈值回调函数
<*@显示二值图片需要放在这里,响应一次,显示一次
************************************************************************/
void on_Threshold( int, void* )
{
//<调用阈值函数
copyImage.copyTo(img);//<绘制轮廓不会消除,需要更换未经处理的图片重新绘制
threshold(gray,binary,thr,255,BinaryType);
Canny(binary,imgThresholded,3,9,3);
findContours(imgThresholded,contours,Hierarchy,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE,Point(0,0));
vector<RotatedRect> box(contours.size());
Point2f vertex[4];
if(contours.size()>0)
{
for (int i=0;i<contours.size();i++)
{
box[i]=minAreaRect(Mat(contours[i]));
box[i].points(vertex);
drawContours(img,contours,i,Scalar(0,0,255),2,8,Hierarchy,0,Point(0,0));
for (int j=0;j<4;j++)
{
line(img,vertex[j],vertex[(j+1)%4],Scalar(255,0,255),2,CV_AA);
}
}
}
imshow("binary image", binary);
imshow("src", img);
}
void ChooseMode()
{
cout<<"Please enter the type you want to select:"<<endl;
cout<<"0、THRESH_BINARY"<<endl; //<大于阈值为白,小于为黑
cout<<"1、THRESH_BINARY_INV"<<endl; //<大于阈值为黑,小于为白
cout<<"2、THRESH_TRUNC"<<endl; //<大于阈值为阈值,小于为原值
cout<<"3、THRESH_TOZERO"<<endl; //<大于阈值为原值,小于为黑
cout<<"4、THRESH_TOZERO_INV"<<endl; //<小于阈值为原值,于为黑
cin>>BinaryType;
cout<<"Please enter the mode you want to select:"<<endl;
cout<<"1、Picture Mode"<<endl;
cout<<"2、Video Mode"<<endl;
cin>>num;
}
代码分析
单轮廓
多轮廓
轮廓矩
轮廓矩中心点
效果图