OpenCV理解
OpenCV的环境配置就不多赘述了,看下面连接
[优快云][1] [1] https://blog.youkuaiyun.com/weixin_37800680/article/details/70991173
读取图片
首先的注意工具栏中的x86要改成x64,因为你vc++目录里额库目录是加入的build文件夹下的x64里路径,这个和电脑是64位的操作系统有关(个人理解)。
```
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv; //包含cv命名空间
int main(int argc, char** argv)
{
Mat src;//定义Mat类型变量
src = imread("D:/HH.jpg");//读取图像
//判断是否读入
if (!src.data)
{
printf("could not load...");
return -1;
}
namedWindow("input", CV_WINDOW_AUTOSIZE);//窗口命名,设置窗口大小
imshow("input", src);//显示图像 参数1:窗口名称 参数2;Mat对象
waitKey(0);//等待任意键按下
return 0;
}
```
这是输出的图片
注意读取图片时的图片的路径要是绝对路径,还有用‘/’而不是‘\’。
窗口命名可以不在双引号下,可以用字符串表示,可以稍微简化一点,例如:
```
char m[] = "input";
namedWindow(m,CV_WINDOW_AUTOSIZE);
imshow(m,dst);
```
当然了,OpeenCV3,如果没有窗口的命名那一句,直接imshow也是可以的,系统会默认开启一个窗口用来显示图片。
图片的修改与保存
1.图片的修改
```这是色彩空间转换的方法,以下的代码是彩色图片转换为灰度图像的方式
Mat dst;
cvtColor(src, dst, CV_BGR2GRAY);//色彩空间转换 参数1:原图,参数2:转换后的图,参数3:转换的方式
namedWindow("output",CV_WINDOW_AUTOSIZE);
imshow("output", dst);
2.图片的保存
```
imwrite("D:/write.jpg", dst);//图片的保存 参数1:保存的路径及图片的格式 参数2:保存的图片
```
Mat对象
Mat对象的构造函数,与常用方法
1.Mat(Size size,int type)
//得到空白图片
Mat dst;
dst = Mat(src.size(), src.type());//参数1:src的尺寸,参数2:src的类型
2.完全拷贝
Mat dst;
法1: dst = src.clone();//得到完全相同的图片
法2: src.copyTo(dst); //得到完全相同的图片
3.得到图片的行列及像素值
Mat dst;
int channels = dst.channels();//得到图片的通道数
int cols = dst.cols; //得到图片的列
int rows = dst.rows; //得到图片的行
const uchar *firstRow = dst.ptr<uchar>(0);//第一行的像素值
printf("rows: %d\ncols:%d", rows, cols); //输出行与列
printf("first pixel value: %d", *firstRow);//输出第一行像素值
printf("channels为:%d", channels); //输出图片的通道数
4.Mat对象的创建
//前两个参数分别表示行和列,第三个参数CV_8UC3中的8是指每个通道占8位,U表示无符号,C表示Char类型,3表示通道数目是3,第四个参数是向量,表示初始化每个像素值是多少,向量长度对应通道数目一致
Mat M = (100,100,CV_8UC3,Scalar(0,0,255));
读写像素
反差
Mat dst;
//单通道的图片
int height = dst.rows;
int width = dst.cols;
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
int gray = dst.at<uchar>(row, col);
dst.at<uchar>(row, col) = 255 - gray;
}
}
imshow("操作后", dst);
//三通道的图片
int height = dst.rows;
int width = dst.cols;
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
int b = dst.at<Vec3b>(row, col)[0];//给每个像素点的每个通道赋值
int g = dst.at<Vec3b>(row, col)[1];
int r = dst.at<Vec3b>(row, col)[2];
dst.at<Vec3b>(row, col)[0] = 255 - b;//重新赋值
dst.at<Vec3b>(row, col)[1] = 255 - g;
dst.at<Vec3b>(row, col)[2] = 255 - r;
//具体在下面解释
}
}
imshow("操作后", dst);
//简便方法
bitwise_not(dst, src);//反位操作
图像的混合
说到图像的混合就有一个重要的公式:**g(x) = (1-a)f0(x)+af1(x) **---------线性混合操作
f0(x)与f1(x)可以看作是两个图像的各个对应的像素,而a,(1-a)可以看作是两张图像所占的权重。
由此可以看出这两张图片的大小,以及图像的类型要相等
Mat src1, src2, dst;
src1 = imread("D:\HH.jpg");
src2 = imread("D:\cat.jpg");
//判断两张图片是否读入成功
if (!src1.data)
{
printf("图片1 could not load");
return -1;
}
if (!src2.data)
{
printf("图片2 could not load");
return -1;
}
double alpha = 0.5;//定义常量
//判断两个图片的大小以及类型是否相同
if (src1.rows == src2.rows && src1.cols == src2.cols && src1.type() == src2.type())
{
//混合的函数, 参数1、3是两张图片,参数2、4是上面函数的系数,参数5是校验值,参数6是输出的图像
addWeighted(src1, alpha, src2, (1.0 - alpha), 0.0, dst);
namedWindow("混合后", CV_WINDOW_AUTOSIZE);
imshow("混合后", dst);
}
**混合后的图象 **
调整图像的亮度和对比度
首先图像的变换可以看作一下两个方向
1.像素变换–点操作
2.领域操作–区域操作
而调整图像的亮度和对比度时属于像素变换即点操作
首先了解基础的知识
g(i,j) = αf(i,j)+β 其中α>0,β是增益变量(关键的公式)
所谓亮度扩大就是每个像素点白的更白,黑的更黑,这个就主要是β这个增益变量的作用了。
而提高对比度就是两个像素之间的差值变大,及对比度变大,与α有关
重要的API
1.saturate_casr(value) 确保值的大小在0~255之间
2.Mat.at(y,x)[index] = value 给每个像素点的每个通道赋值
Mat src, dst;
src = imread("D:/HH.jpg");
namedWindow("input", CV_WINDOW_AUTOSIZE);
imshow("input", src);
int height = src.rows;
int width = src.cols;
dst = Mat::zeros(src.size(), src.type());
//可以通过两个常变量调整对比度及亮度
float alpha = 1.7;
float beta = 30;
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
float b = src.at<Vec3b>(row, col)[0];
float g = src.at<Vec3b>(row, col)[1];
float r = src.at<Vec3b>(row, col)[2];
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);
}
}
namedWindow("output", CV_WINDOW_AUTOSIZE);
imshow("output", dst);
waitKey(0);//等待任意键安下
return 0;
调高对比度
可以通过调整alpha与β的值调整亮度和对比度
图像的模糊
图像的降噪
要讲图象模糊的作用是降噪,降噪的噪就是一些去除掉那些像素值与周围的像素值差别很大的点,让他们处于一个相对较平滑的趋势,使用Smooth/Blur函数降噪
卷积
卷积就是通过一个卷积核在图片像素中移动进行计算,同时,这种平移计算卷积的操作也可以看成矩阵操作,对于上面一个输入为5x5的输入,核为3x3的卷积来说(无padding且1 strides),把输入、卷积核和输出都展开为向量形式:
由这个图象可以看出5×5的图象用3×3的卷积核进行卷积计算,这样就会使外面两周的像素丢失即边缘像素未处理。最常见的处理方式就是向外扩张。
图像模糊–高斯模糊
这是一维的:
这是二维的:
Mat src, dst;
src = imread("D:/HH.jpg");
namedWindow("input", CV_WINDOW_AUTOSIZE);
imshow("input", src);
//参数1:原图像 参数2:目标图像 参数3:卷积核大小 参数4:(默认值)锚点在核的中心
blur(src, dst, Size(7, 7), Point(-1, -1));
//高斯模糊
//参数1:原图像 参数2:目标图像 参数3:卷积核大小 参数4:标准差
GaussianBlur(src, dst, Size(9, 9), 0);
namedWindow("output", CV_WINDOW_AUTOSIZE);
imshow("output", dst);
blur函数用标准化的盒式过滤器来平滑图像
GaussianBlur函数是使用高斯分布的理论推导的
除此之外还有中值模糊函数:medianBlur
双边滤波函数bilateralFilter
降噪:[优快云]https://blog.youkuaiyun.com/wss794/article/details/81144607
[优快云]https://blog.youkuaiyun.com/renhaofan/article/details/80268082
[优快云] https://blog.youkuaiyun.com/qq_39861376/article/details/82109127
[优快云]https://blog.youkuaiyun.com/xylin1012/article/details/81807553