栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

OpenCV学习之道

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

OpenCV学习之道

一, 前言

        作为入门OpenCV的新手,首先感觉到的便是图像处理中数学知识的丰富,今天我也来谈一谈对于图像掩膜操作的认识与理解。

二,对于图像掩膜操作的认识与理解

1,什么是图像掩膜?

        图像掩膜就是通过一个固定的卷积核来对原图像进行卷积,然后达到提高对比度,提取感兴趣区域,屏蔽区域,结构特征提取或者实现特殊形状的制作。这篇文章,我们围绕着其中一点,也就是提高图像对比度来展开。其中关于提高对比度的卷积核为下图所示。


        

 2,什么是卷积操作?
        当我第一次了解掩膜操作时,我也会听到其中夹杂着一个卷积操作,听的我们一愣一愣的,可是卷积操作究竟是什么呢?
        我们都知道,图像就是由一个一个矩阵组成的,而关于图像的信息也便是储存在矩阵的每个元素当中,当我们对于矩阵中的元素进行操作时,图像的信息改变,之后图像呈现出来的样子也会得到改变,卷积操作也便是改变信息的一种方法。
        卷积就是在自定义卷积核的基础之上,在输入原图像上实现矩阵元素上一一对应着依次相乘后相加然后将得到的数值赋给输出图像上对应的元素点,然后不断循直到操作完整张图片。下面用一个图像来详细的展示一下关于图像卷积的操作。

        其中我来稍微解释一下,根据上述卷积核,首先从能够实现卷积的第一中心出发,也便是坐标为(2, 2)的位置与卷积核的中心对应,各个元素相互对应,然后实现元素的依次相乘再相加得到一个新的数值,再将其赋值给新图像的对应位置(2, 2),然后不断的循环,直到达到最后一个能够操作的像素点(n-1,n-1), 这便实现了一个完整的图像卷积操作(当然,从中我们也会看到其中的缺点,就是图像的边缘信息一般得不到处理)

卷积操作理解了,接下来我们来实现一下类似于底层的代码操作

#include 
#include 
using namespace std;
using namespace cv;
int main(int argc,char* argv[]){
    Mat src,dst;
    src = imread("......");
	if(!src.data){
        cout<<"Could not load image...n";
        return -1;
    }
    namedWindow("Src",WINDOW_AUTOSIZE);
    imshow("Src",src);
    
    int cols = src.cols;
    int rows = src.rows;
    int offsetx = src.channels;
    dst = Mat::zeros(src.size(),src.type());
    
    for(int i=1;i(i-1);
        const uchar* NowLine = src.ptr(i);
        const uchar* NextLine = src.ptr(i+1);
        uchar* out = dst.ptr(i);
        for(int j=offsetx;j(5*NowLine[j]-(NowLine[j-1]+NowLine[j+1]+LastLine[j]+NextLine[j]);
        }
    }
    namedWindow("Dst",dst);
    imshow("Dst",dst);
    waitKey(0);
	return 0;
}

接下来我们来实现简洁的API实现操作

#include 
#include 
using namespace std;
using namespace cv;
int main(int argc,char* argv[]){
    Mat src,dst;
    src = imread("......");
    if(!src.data){
        cout<<"Could not load image...n";
        return -1;
    }
    namedWindow("Src",WINDOW_AUTOSIZE);
    imshow("Src",src);

    Mat kernel = (Mat_(3, 3)) <<0,-1,0,-1,5,-1,0,-1,0);

    filter2D(src,dst,-1,kernel);
    //其中第三个参数可以默认-1,-1代表默认src的深度
    namedWindow("Dst", dst);
    imshow("Dst",dst);
    waitKey(0);
}
三,相关API的解析

        (1), dst = Mat::zeros(src.type(), src.size());表示创建一张与src图像一模一样的空白图像;
        (2), src.cols;src.rows;src.channels;从前往后分别表示图像矩阵的列数,行数,以及通道数;
        (3), const uchar* NowLine = src.ptr(i)表示获取该图像第i行的地址;  
        (4), saturate(i) 类似于取绝对值,其中< >中规定( )中数据的范围,uchar代表unsigned char 数据取值为0~255之间,所以当 i 超过255,i 便取值255,当 i 小于0,i便取值0;

        (5), filter2D(Mat src,Mat dst, -1,kernel);可以用来实现卷积操作,src为输入图像,dst为输出图像,第三个参数要填写输入图像的深度即 src.depth(), 一般填写-1即是默认为输入图像的深度,第四个参数即是自定义的卷积核。

四,总结

        这篇文章讲解了关于掩膜操作是什么,具有什么作用,卷积操作是什么,具有什么作用,以及一些API和关于掩膜操作代码的演示,当我们深入了解也会发现有些时候卷积核的取值能够出现许多眼前一亮的效果,我也希望大家能够创建出自己的卷积核,实现许多有用的效果,解决许多实际的问题。

       本篇文章是属于学习类型的,讲解的不够详细,有错误也希望各位大佬能够及时的指出,大家相互学习学习。

 

 

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/925420.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号