讲了一个最小二乘法问题(存在四个不在一条直线上点,拟合一条直线,使这条直线能够
误差最小的穿过这四个点)虽然还不知道具体怎么解。
引申到矩阵的最小二乘法(有三个矩阵A,B,C,A为4 * 2,C为4 * 1,A * B = C.求B矩阵)
求B,A矩阵是一个非奇异矩阵,不可逆,所以让A转置左乘A构成满秩矩阵C,可得B等于C逆乘上A转置再乘C
图像是由波组成的
介绍了矩阵的求导(雅可比矩阵)
#include "opencv.hpp"
#include
using namespace std;
using namespace cv;
void main()
{
//读取摄像机程序
VideoCapture cap(0);
while(true)
{
Mat frame;
cap >> frame;
// namedWindow("123",1);//此时,窗口不可调节大小
namedWindow("123",0);//此时,窗口可调节大小
imshow("123",frame);
waitKey(30);//不断刷新图像
}
Mat imggray = imread("123.jpg",1);
cvtColor("imggray,imggray,CV_RGB2GRAY");//转换图片颜色为灰色
cout << (int)imggray.at<uchar>(1,1) <//读取像素值
imshow("123",1);
waitKey(0);//读图片周一帧,无需延时
灰度图为单通道图像;
彩图分为3通道和4通道两种:RGB为3通道;
RGBA为4通道,A代表透明度(0,255);
在opencv宏定义中:
CV_8UCI ——char
CV_32SC1——int
CV_32FC1——float
CV_64FC1——double
显示时常用char类型
具体操作计算时用double类型。
Mat image = Mat::eye(5,5,CV_64FC1);//定义5*5单位阵
Mat image = Mat::ones(5,5,CV_64FC1);//元素全为1
Mat image = Mat::zeros(5,5,CV_64FC1);//元素全为0
Mat image = Mat::eye(5,5CV_64FC1);
image copyTo()//拷贝矩阵
image inv()//对矩阵求逆
对图像进行求导是对像素值组成的二维矩阵进行的求导运算,求得的导数就是高斯噪声;
对矩阵求导在高等数学中有具体的定义和公式;
此时引入了卷积的概念,作为一个小白,在经过自己的亲身实验后,我现在可以体会到卷积在图像处理中的强大作用;
对图像求导可以不用理解较难的数学公式,直接使用卷积模板进行求解;
卷积其实就是加权求和,卷积模板就是权值>
目前我认为,我们可以定义许多种卷积模板,并用图像的像素值*卷积模板达到特殊的像素强度分配,从而达到一些效果,例如:具体讲到的高斯模板就可以使图像达到模糊的效果;还有sobel模板是对图像进行边缘处理。
我们先找一张图片,先用灰度图转换后读出来
使用了矩阵求导公式
DX=f(x+1,y)−f(x−1,y)
void main()
{
Mat imggray = imread("123.jpg",1);
cvtColor(imggray,imggray,CV_RGB2GRAY);
namedWindow("123",1);
cout<<"row"<"cols"<2,CV_8UC1);
for(int i = 0;i//i行,j列
{
for(int j = 1;j1;j++)
{
dimg.at<uchar>(i,j - 1) = imggray.at<uchar>(i,j - 1) - imggray.at<uchar>(i,j + 1);
}
}
mshow("123",dimg);
waitKey(10);//线程等待
system("pause");
}
效果是这样的
下面进行卷积求导。
void main()
{
Mat imggray = imread("123.jpg",1);
cvtColor(imggray,imggray,CV_RGB2GRAY);
namedWindow("123",1);
Mat dimg=Mat(imggray.rows,imggray.cols-2,CV_8UC1);
Mat model=Mat(1,3,CV_64FC1);
//定义卷积模板
model.at<double>(0,0)=1;
model.at<double>(0,1)=0;
model.at<double>(0,2)=-1;
for(int i=0;ifor (int j=1;j1;j++)
{
int half=model.cols/2;
double sum=0;//加权平均
for (int m=0;mfor (int n=-half;ndouble)(imggray.at<uchar>(i+m,j+n))*model.at<double>(m,n+half);
}
}
dimg.at<uchar>(i,j-1)=(uchar)sum;
}
}
imshow("123",dimg);
waitKey(10);
system("pause");
}
}
和上面的求导效果是一样的 。
高斯模糊就是用正态分布作为权重分配方式。
正态分布的密度函数叫做高斯函数
这是一维形式
因为图像都是二维的,我们需要推导出高斯函数的二维形式,如下
下面进行高斯模糊的卷积核创建和卷积操作
void main()
{
Mat imggray = imread("123.jpg",1);
cvtColor(imggray,imggray,CV_RGB2GRAY);
namedWindow("123",1);
//构建高斯模板
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<double>(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<double>(i+2,j+2)/=gssum;
}
}
//进行卷积操作
Mat dimg=Mat(imggray.rows-4,imggray.cols-4,CV_8UC1);
for (int i=2;i2;i++)
{
for (int j=2;j2;j++)
{
double sum=0;
for (int m=0;mfor (int n=0;nsum+=(double)(imggray.at(i+m-2,j+n-2))*gauss.at<double>(m,n);
}
}
dimg.at(i-2,j-2)=(uchar)sum;
}
}
imshow("gauss",dimg);
waitKey(0);
}
效果是这样的
达到了模糊的效果,我们可以通过改变sigma的值来决定模糊的程度
前面说到了sobel,它用来处理边缘效果,在opencv中只需直接调用即可,同样高斯模糊也可以直接调用
GaussianBlur(frame,frame,cvSize(5,5),10,10);高斯模糊函数
我们现在来看一下soble函数对图像处理后的效果
void main()
{
Mat imggray = imread("123.jpg",1);
cvtColor(imggray,imggray,CV_RGB2GRAY);
namedWindow("123",1);
Sobel(imggray,imggray,0,1,1);
imshow("q",imggray);
waitKey(10);
system("pause");
}
可以看到只保留了边缘部分
也许这就叫滤波,这些也许都叫滤波,目前还没有完全理解…