目录:
*第一节——基础——加载imread、修改、显示imshow、保存imwrite
*第二节——矩阵的掩模操作filter2D+++代码的运行时间getTickCount
*第三节——Mat对象create、clone、copyTo、cvtColor、cout
*第四节——图像操作——访问图像像素点进行反差操作bitwise_not
*第五节——图像混合——两张大小相等类型相同的图像进行线性混合操作addWeighted
*第六节——提高图像亮度与对比度
*第七节——绘制形状与文字-线line、矩形rectangle、椭圆ellipse、圆circle、多边形fillPoly、随机线与文字
*第八节——图像模糊-去噪-均值blur、高斯GaussianBlur、中值medianBlur、双边bilateralFilter
*第九节——形态学操作——膨胀dilate和腐蚀erode
*第十节——形态学操作morphologyEx——开操作、闭操作、形态学梯度、顶帽、黑帽
*第十一节——形态学操作应用-提取水平与垂直线
*第十二节——图像金字塔——图像上采样pyrUp(zoom in放大)和降采样pyrDown(zoom out缩小)
*第十三节——基本阈值操作threshold
*第十四节——自定义线性滤波——Robert、Sobel、拉普拉斯算子、filter2D
*第十五节——边缘处理——copyMakeBorder用途:在卷积时边界的处理方式有4种类型
*第十六节——Sobel——边缘处理
*第十七节——Laplacian——边缘处理
*第十八节——Canny——边缘处理
*第十九节——霍夫变换——直线变换HoughLinesP
*第二十节——霍夫变换——圆变换HoughCircles
*第二十一节——像素重映射remap
*第二十二节——直方图均衡化equalizeHist
*第二十三节——直方图计算calcHist
*第二十四节——直方图比较compareHist
*第二十五节——直方图反向投影calcBackProject
*第二十六节——模板匹配matchTemplate
*第二十七节——轮廓发现findContours
*第二十八节——凸包convexHull
*第二十九节——轮廓周围绘制矩形框和圆形框
*第三十节——图像矩moments、面积contourArea, 弧长arcLength
*第三十一节——点多边形测试
*第三十二节——点多边形测试
///第一节——基础——加载imread、修改、显示imshow、保存imwrite*///
//添加头文件
#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui/highgui.hpp>
//命名空间
using namespace cv;
using namespace std;
//程序入口
int main(int argc, char** argv)
{
//加载图像
Mat src = imread("E:/images/test.jpg");
if (src.empty()) {
printf("error\n"); return -1;}
//if(!src1.data) {cout << "error..." << endl; return -1;}//不同的表达方式
///CV_Assert(testImage.depth() == CV_8U);//若括号中的表达式值为false,则返回一个错误信息_同上一句的效果
namedWindow("opencv setup demo", CV_WINDOW_AUTOSIZE);//创建一个显示窗口
imshow("opencv setup demo", src);//显示图像
//修改图像
Mat dst;
cvtColor(src, dst, CV_BGR2HSV);//色彩空间转换
imshow("output window", dst);//显示修改后的图像
//保存图像
imwrite("E:/images/repair.png", dst);
waitKey(0);
return 0;
}
///第二节——矩阵的掩模操作filter2D+++代码的运行时间getTickCount*/
int main(int argc, char** argv)
{
//代码运行开始时间
double t = getTickCount();
//使用Filter2D函数——掩模操作
Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
filter2D(src, dst, src.depth(), kernel);
//filter2D(src, csrc, -1, kernel);//-1默认和src的深度一样
//代码运行时间=结束时间-开始时间 //转换时间单位并输出代码运行时间
double timeconsume = (getTickCount() - t) / getTickFrequency();
printf("timeconsume %.2f\n", timeconsume);//输出消耗的时间
}
///第三节——Mat对象create、clone、copyTo、cvtColor、cout*/
int main(int argc, char** argv)
{
//创建一个与输入图像src大小、类型一致的图像,且初始化像素为红色
Mat dst = Mat(src.size(), src.type(), Scalar(0, 0, 255));//初始化的像素值,(0, 0, 255)表示红色
//同上的另一种创建方法
Mat m1;
m1.create(src.size(), src.type());
m1 = Scalar(0, 0, 255);
//克隆
Mat dst = src.clone();
//复制
Mat dst;//clone copyTo 两种
src.copyTo(dst);
//将图像转为灰度图像,并显示:输入图像和输出图像的通道结果
cvtColor(src, dst, CV_BGR2GRAY);
printf("input image channels : %d\n", src.channels()); //3通道
printf("output image channels : %d\n", dst.channels()); //1通道
//显示输出图像的宽和高以及输出图像第一个像素值
cvtColor(src, dst, CV_BGR2GRAY);
int cols = dst.cols;//dst的全部列(宽)
int rows = dst.rows;//dst的全部行(高)
printf("rows : %d cols : %d\n", rows, cols);
const uchar* firstRow = dst.ptr<uchar>(0);//访问图像的像素值
printf("fist pixel value : %d\n", *firstRow);//第一个像素值是多少
//定义一个3×3的图像,数据结构为CV_8UC3
Mat M(3, 3, CV_8UC3, Scalar(0,0,255));//3通道,(0,0,255)
imshow("out image", M);
cout << "M =" << endl << M << endl;//一种打印方式
//定义一个100×100的图像,数据结构为CV_8UC1
Mat M(100, 100, CV_8UC1, Scalar(127)); //1通道 127
cout << "M =" << endl << M << endl;
//创建新的窗口——全部初始化为0,图像为黑漆漆的一片,类似于眼睛
Mat m1 = Mat::zeros(2, 2, CV_8UC1);//参数(row,col,type)(行-高,列-宽,类型)
Mat m2 = Mat::zeros(src.size(), src.type());//和原图大小一样
Mat m3 = Mat::eye(2, 2, CV_8UC1);
cout << "m2 =" << endl << m2 << endl;
}
///第四节——图像操作——访问图像像素点进行反差操作bitwise_not*/
int main(int argc, char** args)
{
//单通道图像反差
Mat grayImg;
cvtColor(src, grayImg, CV_BGR2GRAY);//cvtColor(src, grayImg, COLOR_BGR2GRAY);
// int height = grayImg.rows;//行
// int width = grayImg.cols;//列
// for (int row = 0; row < height; row++)
// {
// for (int col = 0; col < width; col++)
// {
// int gray = grayImg.at<uchar>(row, col);
// grayImg.at<uchar>(row, col) = 255 - gray;//反差之后的像素
// }
// }
bitwise_not(grayImg, grayImg); //调用函数等同于for循环的内容 反差图片
//三通道——彩色图像的反差处理
Mat dst;
dst.create(src.size(), src.type());
int height3 = src.rows; int width3 = src.cols; int channels = src.channels();//获取通道
printf("height=%d width=%d channels=%d\n", height, width, channels);
// for (int row = 0; row < height3; row++)
// {
// for (int col = 0; col < width3; col++)
// {
// if (channels == 1)
// {
// int gray = grayImg.at<uchar>(row, col);
// grayImg.at<uchar>(row, col) = 255 - gray;//反差之后的像素
// }
// else if (channels == 3)
// {
// int b = src.at<Vec3b>(row, col)[0];//blue
// int g = src.at<Vec3b>(row, col)[1];//green
// int r = src.at<Vec3b>(row, col)[2];//red
// dst.at<Vec3b>(row, col)[0] = 255 - b;
// dst.at<Vec3b>(row, col)[1] = 255 - g;
// dst.at<Vec3b>(row, col)[2] = 255 - r;
// }
// }
// }
bitwise_not(src, dst); //调用函数等同于for循环的内容 反差图片
}
///第五节——图像混合——两张大小相等类型相同的图像进行线性混合操作addWeighted*/
int main(int argc, char** argv)
{
double alpha = 0.5;
if (src1.rows == src2.rows && src1.cols == src2.cols && src1.type() == src2.type())
{
//add(src1,src2,dst,Mat()); //直接添加的效果
//multiply(src1, src2, dst, 1.0); //相乘的效果
addWeighted(src1, alpha, src2, (1.0 - alpha), 0.0, dst);//线性混合操作
}
else
{
printf("could not blend images , the size of images is not same...\n");
return -1;
}
}
///第六节——提高图像亮度与对比度*/
int main(int argc, char** argv)
{
int height = src.rows;
int width = src.cols;
Mat dst = Mat::zeros(src.size(), src.type());//创建一个和原图像大小和类型一致的空白图像,像素初始化为0
float alpha = 1.5;
float beta = 10;
Mat m1;
src.convertTo(m1, CV_32F);
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
if (src.channels() == 3)
{
float b = m1.at<Vec3f>(row, col)[0];// blue
float g = m1.at<Vec3f>(row, col)[1]; // green
float r = m1.at<Vec3f>(row, col)[2]; // red
// output
dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(b*alpha + beta);
dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(g*alpha + beta);
dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(r*alpha + beta);
}
else if (src.channels() == 1)
{
float v = src.at<uchar>(row, col);
dst.at<uchar>(row, col) = saturate_cast<uchar>(v*alpha + beta);
}
}
}
}
///第七节——绘制形状-线line、矩形rectangle、椭圆ellipse、圆circle、多边形fillPoly、随机线与文字*/
Mat src;//定义的全局变量
const char* drawdemo_win = "draw shapes and text demo";
//函数声明
void MyLines();/*线*/ void MyRectangle();/*矩形*/ void MyEllipse();/*椭圆*/
void MyCircle();/*圆*/ void MyPolygon();/*多边形*/ void RandomLineDemo();/*随机线*/
int main(int argc, char** argv)
{
//函数调用
MyLines();
MyRectangle();
MyEllipse();
MyCircle();
MyPolygon();//多边形
//绘制文字
putText(src, "Hello OpenCV", Point(300, 300),CV_FONT_HERSHEY_COMPLEX, 1.0,Scalar(12, 23, 200), 3, 8);
RandomLineDemo();
}
//函数实现
void MyLines()
{
Point p1 = Point(20, 30);
Point p2;
p2.x = 400;
p2.y = 400;
Scalar color = Scalar(0, 0, 255);//红色
line(src, p1, p2, color, 1, LINE_AA);//1表示线宽
}
void MyRectangle()
{
Rect rect = Rect(200, 100, 300, 300);
Scalar color = Scalar(255, 0, 0);//蓝色
rectangle(src, rect, color, 2, LINE_8);
}
void MyEllipse()
{
Scalar color = Scalar(0, 255, 0);//绿色
/*空心椭圆(src,点中心,尺寸轴,双角度,双起始角,双终止角,颜色,线宽,线型,int shift=0)*/
ellipse(src,Point(src.cols / 2, src.rows / 2),Size(src.cols / 4, src.rows / 8),
90, 0, 360, color, 2, LINE_8);
}
void MyCircle()
{
Scalar color = Scalar(0, 255, 255);
Point center = Point(src.cols / 2, src.rows / 2);
circle(src, center, 150, color, 2, 8);
}
void MyPolygon()
{
Point pts[1][5];
pts[0][0] = Point(100, 100);
pts[0][1] = Point(100, 200);
pts[0][2] = Point(200, 200);
pts[0][3] = Point(200, 100);
pts[0][4] = Point(100, 100);
const Point* ppts[] = {
pts[0] };//多边形的顶点
int npt[] = {
5 };//要绘制的多边形顶点数目
Scalar color = Scalar(255, 12, 255);//颜色
fillPoly(src, ppts, npt, 1, color, 8);//1表示画一个多边形-实心的
}
void RandomLineDemo()
{
RNG rng(12345);//随机数生成函数RNG 12345是随机种子
Point pt1;
Point pt2;
Mat bg = Mat::zeros(src.size(), src.type());//创建一张空白图片,纯黑色
for (int i = 0; i < 100000; i++)
{
pt1.x = rng.uniform(0, src.cols);
pt2.x = rng.uniform(0, src.cols);
pt1.y = rng.uniform(0, src.rows);
pt2.y = rng.uniform(0, src.rows);
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
if (waitKey(50) > 0) //随时可以停止的命令
{
break;
}
line(bg, pt1, pt2, color, 1, 8);
}
}
///第八节——图像模糊-去噪-均值blur、高斯GaussianBlur、中值medianBlur、双边bilateralFilter*/
int main(int argc, char** argv)
{
//均值模糊
blur(src, dst, Size(11, 11), Point(-1, -1));//Point(-1, -1)表示默认正中心
//高斯模糊
GaussianBlur(src, gblur, Size(11, 11), 11, 11);//Size(x,y),x,y必须是正数而且是奇数
//中值滤波 对椒盐噪声有很好的效果
medianBlur(src, dst, 3);
//双边滤波 立体感更强
bilateralFilter(src, dst, 15, 200,