计算机视觉算法

计算机视觉算法第一节个人理解 (一)

讲了一个最小二乘法问题(存在四个不在一条直线上点,拟合一条直线,使这条直线能够
误差最小的穿过这四个点)虽然还不知道具体怎么解。
引申到矩阵的最小二乘法(有三个矩阵A,B,C,A为4 * 2,C为4 * 1,A * B = C.求B矩阵)
求B,A矩阵是一个非奇异矩阵,不可逆,所以让A转置左乘A构成满秩矩阵C,可得B等于C逆乘上A转置再乘C
图像是由波组成的
介绍了矩阵的求导(雅可比矩阵)

开始了Opencv的使用

摄像机的调用

#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模板是对图像进行边缘处理。

对图像进行x方向上的非卷积求导

我们先找一张图片,先用灰度图转换后读出来

使用了矩阵求导公式
DX=f(x+1,y)f(x1,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的值来决定模糊的程度

其他api

前面说到了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");
}


可以看到只保留了边缘部分
也许这就叫滤波,这些也许都叫滤波,目前还没有完全理解…

你可能感兴趣的:(初学)