一、摄像机与视频的读取
VideoCapture cap(0); //打开默认摄像头设备
//1.VideoCapture cap(in device); 如果只有一个设备,device只通过0
//2.VideoCapture cap(const string& filename); filename为要打开的视频文件名
while (true)
{
Mat frame;
cap>>frame; //从摄像头得到一个新的帧
namedWindow("123",0);//创建一个名为 123 的窗口
/*
void namedWindow(const string& winname,int flags);
参数一,const string&型的name,即填被用作窗口的标识符的窗口名称。
参数二,窗口标识flags,可取值:(1)WINDOW_AUTOSIZE,窗口大小会自动调整以适应所显示的图像,且不能手动改变
(2)WINDOW_NORMAL,用户可任意改变窗口大小
(3)WINDOW_OPENGL,所创建窗口支持OpenGL
PS:flasgs项不填时默认其值为WINDOW_AUTOSIZE
*/
imshow("123",frame); //在指定的窗口 123 中显示一幅图像
/*
void imshow(const string& winname, InputArray mat);
参数一,winname,填需要显示的窗口标识名称
参数二,InputArray 类型的mat,填需要显示的图像
*/
waitKey(30); //每处理完一帧,程序会等待30毫秒才会读取下一帧
/*
waitKey(delay);
delay>0,每处理完一帧,程序会等待delay毫秒才会读取下一帧
delay=0,只会显示第一帧视频
*/
}
二、读取图片 与其中的像素值
Mat img_origin=imread("123.jpg",1); //读入三通道彩色图像 123
/*
Mat imread(const string& filename, intflags=1 );
flags>0或flags=CV_LOAD_IMAGE_COLOR,返回一个3通道的彩色图像。
flags=0或flags=CV_LOAD_IMAGE_GRAYSCALE,返回灰度图像。
flags<0,返回包含Alpha通道的加载的图像。
flags=CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR,载入最真实的图像。
*/
Mat img_gray;
cvtColor(img_origin,img_gray,CV_RGB2GRAY); //转(123)彩色图像为灰色
/*
void cvtColor(InuputArray img_origin,OutputArray img_gray,int code,int dstCn=0);
img_origin,原始图像
img_gray,更改后的目标图像
code为一掩码,CV_RGB2GRAY为模式之一,功能:转彩色图像为灰色
*/
cout<<(int)img_gray.at
(1,1)<
三、Mat对象一些操作
Mat imgone = Mat::ones(5,5,CV_64FC1); //建立5行5列零矩阵
Mat imgzero = Mat::zeros(5,5, CV_64FC1); //建立5行5列且所有元素均为1的矩阵
Mat image = Mat::eye(5,5,CV_64FC1); //建立单位阵(主对角线元素均为1)
/* 初始化函数cv::Mat::zeros , cv::Mat::ones , cv::Mat::eye 指定要使用的大小和数据类型*/
Mat sum = image+imgone; //矩阵求和
cout<
<
四、图像x方向求导的卷积与非卷积操作
VideoCapture cap(0);
while (true)
{
Mat frame;
cap>>frame; //读入原图像
cvtColor(frame,frame,CV_RGB2GRAY);
/*非卷积*/
Mat dimg=Mat(frame.rows,frame.cols-2,CV_8UC1); //初始化单通道的目标图像,x方向求导,故比原图像少两列
/*直接将原图像操作矩阵中要产生新像素值的方格左右两侧元素相减,产生目标图像新像素点*/
for (int i=0;i
(i,j-1)=frame.at
(i,j-1)-frame.at
(i,j+1);
}
}*/
/*卷积*/
Mat dimg=Mat(frame.rows,frame.cols-2,CV_8UC1); //在x方向对原图像的卷积操作不处理边界,故产生的目标图像比原图像少两列
Mat model=Mat(1,3,CV_64FC1); //建立1行3列的模板
/*初始化模板*/
model.at
(0,0)=1;
model.at
(0,1)=0; model.at
(0,2)=-1; /*具体卷积操作*/ /*1.卷积操作数矩阵与模板矩阵中对应位置元素相乘求和,产生目标图像的一个像素点*/ /*2.在x方向进行平移,重复操作1,直到处理完原图像*/ for(int i=0;i
(i+m,j+n))*model.at
(m,n+half); } } dimg.at
(i,j-1)=(uchar)sum; } } imshow("123",dimg); waitKey(10); }
五、高斯模糊的核创建与卷积操作
(一)高斯模糊原理
所谓"模糊",即每一个像素都取周边像素的平均值。
上图中,2是中间点,周边点都是1。"中间点"取"周围点"的平均值,就会变成1。在数值上,这是一种"平滑化"。在图形上,就相当于产生"模糊"效果,"中间点"失去细节。
计算平均值时,取值范围越大,"模糊效果"越强烈。
每个点都要取周边像素的平均值,如果使用简单平均,显然不是很合理,因为图像都是连续的,越靠近的点关系越密切,越远离的点关系越疏远。因此,加权平均更合理,距离越近的点权重越大,距离越远的点权重越小。
(二)正态分布的权重
正态分布显然是一种可取的权重分配模式。在图形上,正态分布是一种钟形曲线,越接近中心,取值越大,越远离中心,取值越小。计算平均值的时候,我们只需要将"中心点"作为原点,其他点按照其在正态曲线上的位置,分配权重,就可以得到一个加权平均值。
(三)高斯函数
一维:
二维:
利用函数计算每个点的权重计算高斯模糊( 由高斯函数计算出每个点的权重值,即得到权重矩阵)
(四)计算高斯模糊
1. 对权重矩阵做归一化处理
(1)求出权重矩阵中所有权重之和,
(2)每个点都除以权重之和,使权重之和为一。
2. 计算高斯模糊的值。假设现有9个像素点,每个点灰度值乘以自己的权重值,得到9个值,将这9个值加起来,就是中心点的高斯模糊的值。对所有点重复这个过程,得到高斯模糊后的图像。
PS:如果原图是彩色图片,可以对RGB三个通道分别做高斯模糊。
(五)代码实现
double sigma=50;
Mat gauss(5,5,CV_64FC1);
for (int i=-2;i<3;i++)
{
for (int j=-2;j<3;j++)
{
gauss.at
(i+2,j+2)=exp(-(i*i+j*j)/(2*sigma*sigma)); /*利用二维高斯函数计算每个点的权重*/
}
}
double gssum=sum(gauss).val[0]; /*求权重之和*/
/*权重矩阵做归一化处理*/
for (int i=-2;i<3;i++)
{
for (int j=-2;j<3;j++)
{
gauss.at
(i+2,j+2)/=gssum; /*每个点都除以权重之和,使权重之和为1*/
}
}
//cout<
<
>frame;
cvtColor(frame,frame,CV_RGB2GRAY);
Mat dimg=Mat(frame.rows-4,frame.cols-4,CV_8UC1);
/*图像卷积操作,无边缘处理*/
for (int i=2;i
(i+m-2,j+n-2))*gauss.at
(m,n); } } dimg.at
(i-2,j-2)=(uchar)sum; } } imshow("a",frame); imshow("gauss",dimg); waitKey(10); }
六、相关API操作
VideoCapture cap(0);
while (true)
{
Mat frame;
cap>>frame;
cvtColor(frame,frame,CV_RGB2GRAY);
GaussianBlur(frame,frame,cvSize(5,5),10,10); //调用高斯模糊函数,对图像平滑(模糊)处理
//Canny(frame,frame,100,100); //边缘检测(1.去噪即对原图像或高斯平滑模板做卷积2.寻找图像中的亮度梯度3.跟踪边缘)
//Sobel(frame,frame,0,1,1); //计算图像亮度函数的一阶梯度矢量或法矢量(PS:常用于边缘检测)
imshow("q",frame);
waitKey(10);
}
参考资料:http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html