今天开始更新opencv的学习。
笔者的开发环境选在vs2017+opencv3.2。
何为矩阵的掩膜操作?其实就是选定一部分我们自己感兴趣的区域,在这个区域内对像素进行操作,利用掩膜我们可以重新计算每个像素的像素值。
比如矩阵A:
(1)
0
−
1
0
−
1
5
−
1
0
−
1
0
\begin{matrix} 0 & -1 & 0 \\ -1 & 5 & -1 \\ 0 & -1& 0 \end{matrix} \tag{1}
0−10−15−10−10(1)
这就是一个掩膜,若中间元素为A[i, j],它指的操作就是
A
[
i
,
j
]
=
5
∗
A
[
i
,
j
]
−
A
[
i
,
j
−
1
]
−
A
[
i
,
j
+
1
]
−
A
[
i
+
1
,
j
]
−
A
[
i
−
1
,
j
]
A[i , j] = 5 * A[i , j] - A[i , j-1] - A[i , j+1] - A[i+1 , j] - A[i-1 , j]
A[i,j]=5∗A[i,j]−A[i,j−1]−A[i,j+1]−A[i+1,j]−A[i−1,j]
通过该掩膜我们可以增强图片的对比度。
主要方法:
1.获取图片指针:src.ptr<uchar>(row)[col] 指的是获取Mat对象src的row行col列的像素值,类型定义为uchar,返回值为指针。获取了指针之后就可以对图像像素进行运算。
2.saturate_cast方法是为了令运算后的像素值合法,即位于0-255之间。
#include <opencv2\opencv.hpp>
#include <iostream>
#include <math.h>
// 矩阵的掩膜操作 提高对比度
using namespace cv;
int main(int argc, char** argv) {
Mat src, dst;
src = imread("E:/opencv_testImages/0.jpg");
if (!src.data) {
printf("could not find...\n");
return -1;
}
namedWindow("input image", CV_WINDOW_AUTOSIZE);
imshow("input image", src);
// printf("%d\n%d\n%d", src.channels(), src.cols, src.rows);
int cols = (src.cols-1) * src.channels();
int offsetx = src.channels(); // 通道数 为3
int rows = src.rows;
double t = getTickCount();
dst = Mat::zeros(src.size(), src.type()); // 初始化
for (int row = 1; row < (rows - 1); row++) {
// 获取指针
const uchar* previous = src.ptr<uchar>(row - 1); //上一行
const uchar* current = src.ptr<uchar>(row); //当前行
const uchar* next = src.ptr<uchar>(row + 1); //下一行
uchar* output = dst.ptr<uchar>(row); // output的指针 赋值给它
for (int col = offsetx; col < cols; col++) {
// 左右偏移多少由通道数目决定
output[col] = saturate_cast<uchar>(5 * current[col] - ( current[col - offsetx] + current[col + offsetx] + previous[col] + next[col] ));
// saturate_cast函数为了令rgb值合法(0-255)
}
}
namedWindow("constrast image demo", CV_WINDOW_AUTOSIZE);
imshow("constrast image demo", dst);
double timeconsume = (getTickCount() - t) / getTickFrequency(); //显示运行了多久
printf("tim consume %.2f", timeconsume);
waitKey(0);
return 0;
}
更简单的方法——利用api:
我们可以直接定义一个kernel,交给filter2D函数自动运算,得出来的结果是一样的。
// 定义一个三行三列的矩阵
Mat kernel = (Mat_<float>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
filter2D(src, dst, -1, kernel);
imshow("out2", dst);