计算机视觉(一)简单认识和图像的预处理

(一)简单理解与准备工作

1.计算机视觉是什么

一个模拟人眼识别的结果
让计算机去认知,也就是人工智能

2.计算机视觉的用处

智能汽车、体感游戏、监控追踪、人脸识别、AR/VR、三维重建、测距等等

3.对图像的认识

图像是一种随时间推移的波形图,傅里叶公式将图像从时域中转换到频域中,如下图所示:
计算机视觉(一)简单认识和图像的预处理_第1张图片

4,配置opencv

大致步骤如下:
(1)首先在官网下载opencv,VS2015版本需要适配3.1.0,VS2015之前的版本适配3.0.0即可
(2)下载安装之后,配置环境变量:选择此电脑,右键属性->高级系统设置->环境变量->系统变量->Path->在变量值中添加相应路径,比如我配置的VS2015的路径为D:\Opencv3.1.0\opencv\build\x64\vc14\bin
注意:根据VS的版本和编译器位数选择路径,VS2015只能配置64位;如果VS2013选择VC12文件夹
(3)打开VS,新建一个Visual C++新建Win32控制台项目,注意选择空项目,新建源文件,打开属性管理器,找到Debug|x64(或Wn32)文件夹,找到Microsoft.Cpp.x64.user(或Microsoft.Cpp.win32.user)文件,右键属性,选择通用属性下的VC++目录,在包含目录下添加三条路径D:\Opencv3.1.0\opencv\build\include D:\Opencv3.1.0\opencv\build\include\opencv D:\Opencv3.1.0\opencv\build\include\opencv2,然后在库目录下添加一条路径:D:\Opencv3.1.0\opencv\build\x64\vc14\lib
(4)再点击链接器,选择输入,在附加依赖项处添加文件:opencv_world310d.lib
(5)最后保存属性表,即可永久配置
PS:以上为DEBUG模式下的配置,如果要配置Release模式,步骤均相同,只要第(4)步添加文件时,把d去掉即可

(二)图像的预处理

首先输入头文件

#include
using namespace std;
#include
using namespace cv;

包括C++编译所需要的和使用opencv所需要的
1.读取摄像机和视频
代码如下:

    VideoCapture cap(0);
    while (true)
    {
        Mat frame;//Mat即矩阵Matrix的缩写,opencv最基本的数据结构,初始化一个框架
        cap >> frame;//读取了一帧图像保存在frame
        namedWindow("123",0 );//新建一个窗口
        imshow("123", frame);//显示窗口
        waitKey(30);//在imshow之后如果没有waitKey语句则不会正常显示图像,30即延迟30ms,具体数字根据帧率来定
    }

2.读取图片与其中的像素值
代码如下:

    Mat imggray=imread("123.jpg",1);//初始化并读取一个图片,注意图片存储文件位置
                                    //参数0表示灰度图 参数1表示三通道彩图
                                    //CV_8UC1单通道灰度图 CV_8UC3三通道彩图
    cvtColor(imggray, imggray, CV_RGB2GRAY);//彩图转换为灰度图
    imshow("123", imggray);
    waitKey(0);
    cout <<(int)imggray.at<uchar>(1, 1)<//第二行第二列元素转化成整型输出,读取像素值

3.创建图像和一些常用方法(Mat对象的一些操作)
代码如下:

    Mat image = Mat::eye(5, 5, CV_64FC1);//zeros全初始化为0  ones全为1  eye单位矩阵
    cout << image<< endl;
    Mat imgone = Mat::ones(5, 5, CV_64FC1);//矩阵加减法 行数列数和类型必须完全一样
    Mat sum = image + imgone;//也可换成- *等其他运算符
    cout << sum << endl;
    image.copyTo();//copyTo拷贝  t转置  inv逆矩阵

4.对一个图像在x方向上的求导的非卷积操作
以对一个5×5的图像在x方向上的求导为例,由求导公式D(x)=f(x+1,y)-f(x-1,y)可知,图像边界处的元素无法求导,则应对5×3的元素求导。
代码如下:

    VideoCapture cap(0);
    while (true)
    {
        Mat frame;
        cap >> frame;
        cvtColor(frame, frame, CV_RGB2GRAY);//转换为灰度图
        cout << "row" << frame.rows << "col" << frame.cols << endl;
        Mat dimg = Mat(frame.rows, frame.cols - 2, CV_8UC1);//定义一个5×3的灰度图
        for (int i = 0; i < frame.rows; i++)//5行不变
        {
            for (int j = 1; j < frame.cols - 1; j++)
            //边界的元素无法求导,所以是3列,从第2列的元素开始
                {
                    dimg.at<uchar>(i, j - 1) = frame.at<uchar>(i, j - 1) - frame.at<uchar>(i, j + 1);
                    //对5行5列求导,5行3列,从第一行第二列的元素开始
                }
        }
        imshow("123", dimg);
        waitKey(10);
    }

5.图像卷积(求导的卷积操作)(滤镜)
卷积就是加权求和,卷积模板就是权值。
可根据图片理解,如下图:
计算机视觉(一)简单认识和图像的预处理_第2张图片
计算机视觉(一)简单认识和图像的预处理_第3张图片
以用一个1×3的卷积模板对图像卷积为例
代码如下:

    VideoCapture cap(0);
    while (true)
    {
        Mat frame;
        cap >> frame;
        cvtColor(frame, frame, CV_RGB2GRAY);
        cout << "row" << frame.rows << "col" << frame.cols << endl;
        Mat dimg = Mat(frame.rows, frame.cols - 2, CV_8UC1);
        Mat model = Mat(1, 3, CV_64FC1);
        //定义一个1*3的卷积模板
        model.at<double>(0, 0) = 1;
        model.at<double>(0, 1) = 0;
        model.at<double>(0, 2) = -1;
        //先用两重循环得到求导后结果
        for (int i = 0; i < frame.rows; i++)
        {
            for (int j = 1; j < frame.cols - 1; j++)
            {
                //再进行两重循环,用卷积模板对求导结果进行卷积
                int half = model.cols / 2;
                double sum = 0;
                for (int m = 0; m < model.rows; m++)
                {
                    for (int n = -half; n < model.cols - half; n++)
                    {
                        sum += frame.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);
    }

6.高斯模糊的核创建与卷积操作
正态分布的密度函数公式如下:
计算机视觉(一)简单认识和图像的预处理_第4张图片
代码如下:

    Mat gauss(5, 5, CV_64FC1);//创建高斯图
    double sigma = 50;//定义并初始化模糊度
    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));//直接用exp()套用公式
        }
    }
    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; //归一化操作
        }
    }
    cout << gauss << endl;//opencv可直接输出图像
    //进行卷积操作
    VideoCapture cap(0);
    while (true)
    {
        Mat frame;
        cap >> frame;
        cvtColor(frame, frame, CV_RGB2GRAY);
        Mat dimg = Mat(frame.rows - 4, frame.cols - 4, CV_8UC1);
        for (int i = 2; i < frame.rows - 2; i++)
        {
            for (int j = 2; j < frame.cols - 2; j++)
            {
                //与上面不同的是,没有定义half,本质相同,分别加权求和进行卷积
                double sum = 0;
                for (int m = 0; m < gauss.rows; m++)
                {
                    for (int n = 0; n < gauss.cols; n++)
                    {
                        sum += (double)(frame.at(i + m - 2, j + n - 2))*gauss.at<double>(m, n);//原图强制类型转换为double
                    }
                }
                dimg.at(i - 2, j - 2) = (uchar)sum;
            }
        }
        //显示原图与模糊后的图进行对比
        imshow("a", frame);
        imshow("gauss", dimg);
        waitKey(10);
    }

7.调用API进行高斯模糊、边缘检测
代码如下:

    VideoCapture cap(0);
    while (true)
    {
        Mat frame;
        cap >> frame;
        cvtColor(frame, frame, CV_RGB2GRAY);
        //调用时需要的参数会在VS中显示
        GaussianBlur(frame,frame,cvSize(5,5),10,10);
        //利用GaussianBlur()输入参数直接进行高斯模糊
        Canny(frame, frame, 100, 100);
        //利用Canny算子进行边缘检测
        Sobel(frame, frame, 0, 1, 1);
        //利用Sobel算子进行边缘检测,可与Canny算子对比,更加明显
        imshow("a", frame);
        waitKey(10);
    }

你可能感兴趣的:(计算机视觉)