一.图像的通道
图像的通道就是把图像分解成一个或多个颜色成分,常见的有单通道,三通道和四通道
1.单通道:
灰度图像,一个像素点只需要一个数值即可表示,0-255(0为黑色,255为白色);
2.三通道:
RGB图像,为红绿蓝三种颜色通道的叠加,三个通道缺一不可。每个通道由0-255的数值表示,当使用矩阵表示三个通道时,三个通道是并列表示的,所以rgb的图像矩阵列数为单个通道的列数乘以通道数。
二.获取图像像素指针
(1) CV_Assert(myImage.depth() == CV_8U);
刚进入函数的时候,我们要确保输入图像是无符号字符类型的。为了做到这点,我们使用了 CV_Assert 函数。若该函数括号内的表达式为false,则会抛出一个错误。
表示了矩阵中元素的类型以及矩阵的通道个数,它是一系列的预定义的常量,其命名规则为CV_(位数)+(数据类型)+(通道数)
S = 有符号整型 U = 无符号整型 F = 浮点型
CV_8U - 8位无符号整数
CV_8S - 8位有符号整数
CV_16U - 16位无符号整数
C1,C2,C3,C4则表示通道是1,2,3,4
_____________________________________________________________________________
(2) Mat.ptr<uchar>(int i=0)
获取像素矩阵的指针,索引i表示第几行,从0开始计行数。
_____________________________________________________________________________
(3) 获得当前行指针const uchar* current= myImage.ptr<uchar>(row );
_____________________________________________________________________________
(3) 获取当前像素点P(row, col)的像素值 p(row, col) =current[col]
矩阵的掩膜操作十分简单,根据掩膜来重新计算每个像素的值,掩膜mask也称为kernel
三.下面这个公式表示提高图像的对比度
用5倍当前像素的值减去该像素上、下、左、右四个像素值和,得到的结果赋值给当前像素。使用该公式可以用于提升图像的对比度。调节I(i,j)的系数权重可以得到不同的对比度提升效果。
I(i,j) = 5*I(i,j) - [I(i-1,j) + I(i+1,j) + I(i,j-1) + I(i,j+1)]
像素范围处理saturate_cast<uchar>
saturate_cast<uchar>(-100),返回0
saturate_cast<uchar>(2888),返回255
小于0返回0,大于255返回255 这个函数确保像素值在0到255之间
矩阵掩膜操作(对比度提高,立体感增强)
数字图像处理中,掩模为二维矩阵数组,有时也用多值图像。数字图像处理中,图像掩模主要用于:
- 提取感兴趣区,用预先制作的感兴趣区掩模与待处理图像相乘,得到感兴趣区图像,感兴趣区内图像值保持不变,而区外图像值都为0。
- 屏蔽作用,用掩模对图像上某些区域作屏蔽,使其不参加处理或不参加处理参数的计算,或仅对屏蔽区作处理或统计。
- 结构特征提取,用相似性变量或图像匹配方法检测和提取图像中与掩模相似的结构特征。
- 特殊形状图像的制作。
四.代码实现
#include<opencv2\opencv.hpp>
#include<iostream>
#include<math.h>
using namespace cv;
int main(int argc, char **argv)
{
Mat src = imread("D:/opencv learning/meinv.jpg", -1);
if (src.empty())
{
printf("could not load image....\n");
return -1;
}
namedWindow("input image", WINDOW_AUTOSIZE);
imshow("input image", src);
//进行掩膜操作的代码
Mat dst = Mat::zeros(src.size(), src.type());//输出图片进行初始化。
//不调用filter 2D 函数,自己编写掩膜操作
/*
int cols = (src.cols-1) * src.channels(); //实际的长度cols等于RGB图像的长度乘以通道数。col为列,去除了最后一列
int offsetx = sr-c.channels();//图像的通道数,例如RGB图像为3通道
int rows = (src.rows-1); //图像的高度。row为行,去除了最后一行
for (int row = 1; row < rows; row++) //从第二行到倒数第二行,去除边缘的行
{
const uchar *previous = src.ptr<uchar>(row - 1);//定义指向上一行的指针,指针是uchar型,不能是int型,会引起图像变形
const uchar *count = src.ptr<uchar>(row);//定义指向当前行的指针
const uchar *next = src.ptr<uchar>(row + 1);//定义指向下一行的指针
uchar *output = dst.ptr<uchar>(row);//定义指向输出图像当前行的指针
for (int col = offsetx; col< cols; col++)//从第二列到倒数第二列,去除边缘列
{
output[col] = saturate_cast<uchar>(5 * count[col] - (previous[col] + next[col] + count[col + offsetx] + count[col - offsetx]));
//掩膜计算公式
}
}
*/
//显示运行时间
double t = getTickCount();//当前的运行周期数
//用filter 2D 函数进行掩膜操作
Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);//定义掩膜
filter2D(src, dst, src.depth(), kernel);
t = ((double)getTickCount() - t) / getTickFrequency();//运行时间
std::cout << "消耗的时间:" << t << std::endl;
namedWindow("output image", WINDOW_AUTOSIZE);
imshow("output image", dst);
waitKey(0);
return 0;
}
图像效果(对比度提高效果)