OPENCV基础笔记

本文深入探讨了OpenCV中的MAT矩阵结构,包括矩阵头信息、引用计数机制以及如何创建ROI。此外,还介绍了颜色系统,如RGB、HSV、HLS及其在图像处理中的应用。计时方法通过getTickCount()和getTickFrequency()进行阐述,并展示了内存模型与高效访问。最后,文章讨论了矩阵加权求和和查表法在图像处理中的高效应用。
摘要由CSDN通过智能技术生成


前言

提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、MAT矩阵

基本上讲 Mat 是一个类,由两个数据部分组成:矩阵头(包含矩阵尺寸,存储方法,存储地址等信息)和一个指向存储所有像素值的矩阵(根据所选存储方法的不同矩阵可以是不同的维数)的指针。
同时不要忘了我们正在讨论的是计算量很大的图像处理算法,因此,除非万不得已,我们不应该拷贝 大 的图像,因为这会降低程序速度。
OpenCV使用引用计数机制。其思路是让每个 Mat 对象有自己的信息头,但共享同一个矩阵。这通过让矩阵指针指向同一地址而实现。而拷贝构造函数则 只拷贝信息头和矩阵指针 ,而不拷贝矩阵。

你可以创建只引用部分数据的信息头。比如想要创建一个感兴趣区域( ROI ),你只需要创建包含边界信息的信息头:

Mat D (A, Rect(10, 10, 100, 100) ); // using a rectangle
Mat E = A(Range:all(), Range(1,3)); // using row and column boundaries
但某些时候你仍会想拷贝矩阵本身(不只是信息头和矩阵指针),这时可以使用函数 clone() 或者

copyTo() 。
Mat F = A.clone();
Mat G;
A.copyTo(G);

M.create(4,4, CV_8UC(2));
这个创建方法不能为矩阵设初值,它只是在改变尺寸时重新为矩阵数据开辟内存。

二、颜色系统

RGB是最常见的,这是因为人眼采用相似的工作机制,它也被显示设备所采用。
HSV和HLS把颜色分解成色调、饱和度和亮度/明度。这是描述颜色更自然的方式,比如可以通过抛弃最后一个元素,使算法对输入图像的光照条件不敏感。
YCrCb在JPEG图像格式中广泛使用。
CIE Lab*是一种在感知上均匀的颜色空间,它适合用来度量两个颜色之间的 距离 。
“HLS 是Hue(色相)、Luminance(亮度)、Saturation(饱和度)。
HSV 色调(H),饱和度(S),明度(V)。
Scalar 是个short型vector
具体说明HSV/HSB与HLS的区别
首先, HSB 和 HSV 是同一个东西,只是名称不同,本文后面仅使用 HSB,当提到它的时候,也代表 HSV。

HSB 和 HSL 在字面意思上是一样的:

H 指的是色相(Hue),就是颜色名称,例如“红色”、“蓝色”; S 指的是饱和度(Saturation),即颜色的纯度;
L(Lightness) 和 B(Brightness)是明度,颜色的明亮程度 在原理和表现上,HSL 和 HSB 中的 H(色相)
完全一致,但二者的 S(饱和度)不一样, L 和 B (明度 )也不一样:

HSB 中的 S 控制纯色中混入白色的量,值越大,白色越少,颜色越纯; HSB 中的 B 控制纯色中混入黑色的量,值越大,黑色越少,明度越高
HSL 中的 S 和黑白没有关系,饱和度不控制颜色中混入黑白的多寡; HSL 中的 L 控制纯色中的混入的黑白两种颜色。

常用的一种方法是 颜色空间缩减 。其做法是:将现有颜色空间值除以某个输入值,以获得较少的颜色数。例如,颜色值0到9可取为新值0,10到19可取为10,以此类推。
uchar (无符号字符,即0到255之间取值的数)类型的值除以 int 值,结果仍是 char 。因为结果是char类型的,所以求出来小数也要向下取整。

三、计时

另外有个问题是如何计时。没错,OpenCV提供了两个简便的可用于计时的函数 getTickCount() 和 getTickFrequency() 。第一个函数返回你的CPU自某个事件(如启动电脑)以来走过的时钟周期数,第二个函数返回你的CPU一秒钟所走的时钟周期数。这样,我们就能轻松地以秒为单位对某运算计时:
double t = (double)getTickCount();
// 做点什么 …
t = ((double)getTickCount() - t)/getTickFrequency();
cout << "Times passed in seconds: " << t << endl;

四、内存模型及访问

在这里插入图片描述

对于Mat的ptr函数,返回的是<>中的模板类型指针,指向的是()中的第row行的起点 通常<>中的类型和Mat的元素类型应该一致
然后再用该指针去访问对应col列位置的元素

单通道 cv::Mat image = cv::Mat(400, 600, CV_8UC1); //定义了一个Mat变量image。
uchar * data00 = image.ptr(0); //data00是指向image第一行第一个元素的指针。
uchar * data10 = image.ptr(1); //data10是指向image第二行第一个元素的指针。
uchar * data01 = image.ptr(0)[1];//data01是指向image第一行第二个元素的指针。

多通道 cv::Mat image = cv::Mat(400, 600, CV_8UC3); //宽400,长600,3通道彩色图片
cv::Vec3b * data000 = image.ptrcv::Vec3b(0); cv::Vec3b * data100 =
image.ptrcv::Vec3b(1); cv::Vec3b * data001 =
image.ptrcv::Vec3b(0)[1]; cv::Vec3b * data

高性能查表法:

Mat& ScanImageAndReduceC(Mat& I, const uchar* const table) {
// accept only char type matrices
CV_Assert(I.depth() != sizeof(uchar));
int channels = I.channels();
int nRows = I.rows;
int nCols = I.cols * channels
//判断此处是否为连续存储
if (I.isContinuous())
{
nCols = nRows;
nRows = 1;
}
int i,j;
uchar
p;
for( i = 0; i < nRows; ++i)
{
p = I.ptr(i);
for ( j = 0; j < nCols; ++j)
{
p[j] = table[p[j]];
}
}
return I; }
迭代法:
Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table) {
// accept only char type matrices
CV_Assert(I.depth() != sizeof(uchar));

const int channels = I.channels();
switch(channels)
{
case 1: 
    {
        MatIterator_<uchar> it, end; 
        for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it)
            *it = table[*it];
        break;
    }
case 3: 
    {
        MatIterator_<Vec3b> it, end; 
        for( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end; ++it)
        {
            (*it)[0] = table[(*it)[0]];
            (*it)[1] = table[(*it)[1]];
            (*it)[2] = table[(*it)[2]];
        }
    }
}

return I;

最高效的Lut操作:
//查找表,数组的下标对应图片里面的灰度值  
//例如lutData[20]=0;表示灰度为20的像素其对应的值0.  
//可能这样说的不清楚仔细看下代码就清楚了。  
uchar lutData[256];  
for (int i = 0; i<256; i++)  
{  
    if(i<=100)  
    lutData[i] =0;  
    if (i > 100 && i <= 200)  
        lutData[i] = 100;  
    if (i > 200)  
        lutData[i] = 255;  
}  
Mat lut(1, 256, CV_8UC1, lutData);

五、矩阵加权求和

在这里插入图片描述

saturate_cast<uchar>主要是为了防止颜色溢出操作

原理大致如下

if(data<0) 

        data=0; 

elseif(data>255) 

    data=255;
Mat kern = (Mat_<char>(3,3) <<  0, -1,  0,
                           -1,  5, -1,
                            0, -1,  0); 

然后调用 filter2D 函数,参数包括输入、输出图像以及用到的核: filter2D(I, K, I.depth(), kern );

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

颢师傅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值