一、图像对比度提升(掩膜操作)
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace cv;
int main(int argc, char** argv) {
Mat src, dst;
src = imread("C:\\Users\\Administrator\\Desktop\\test.jpg");
if (!src.data) {
printf("could not load image...\n");
return -1;
}
namedWindow("input image", CV_WINDOW_AUTOSIZE);
imshow("input image", src);
//第一种提升对比度的方式
/*int cols = (src.cols-1) * src.channels();
int offsetx = src.channels();
int rows = src.rows;
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);
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]));
}
}*/
//第二种提升对比度的方式
double t = getTickCount();
Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1,6, -1, 0, -1, 0);
filter2D(src, dst, src.depth(), kernel);
double timeconsume = (getTickCount() - t) / getTickFrequency();
printf("tim consume %.2f\n", timeconsume);
namedWindow("contrast image demo", CV_WINDOW_AUTOSIZE);
imshow("contrast image demo", dst);
waitKey(0);
return 0;
}
以上代码中主要的几个知识点解释下:
1.掩膜操作。这是提高图像对比度的一种方法,根据掩膜重新计算每个像素的像素值。
先看公式:
如下图,红色是中心像素,从上到下,从左到右对每个像素做同样的处理操作,得到最终结果就是对比度提高之后的输出图像Mat对象。
2.Mat dst = Mat::zeros(src.size(), src.type());//返回指定大小和类型的零数组。即创建一个空的图像。
3.saturate_cast<uchar>();//确保RGB值范围在0--255之间.
4.Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1,5, -1, 0, -1, 0);//创建一个3*3的掩膜,用于提升对比度。
5.filter2D(src, dst, src.depth(), kernel);将图像根据掩膜与src.depth()【位深度 8、16、24等】生成目的图像。
6.getTickCount();用于返回从操作系统启动到当前所经的计时周期数。
7.getTickFrequency();用于返回CPU的频率。这里的单位是秒,也就是一秒内重复的次数。
打印运行时间例子:
double t = getTickCount();
。。。。。。
double timeconsume = (getTickCount() - t) / getTickFrequency();
printf("tim consume %.2f\n", timeconsume);
二、Mat对象详解
这节没有示例代码。:)
1.构造函数。
(1)Mat(Size size,int type)
举例从一个Mat图像复制dst = Mat(src.size(), src.type());
(2)Mat(int rows,int cols,int type,const Scalar &s)
举例新建一个Mat M(100, 100, CV_8UC1, Scalar(127));
或者Mat M(100, 100, CV_8UC3, Scalar(0,0,255));
CV_8UC1与CV_8UC3的理解是8代表位深度,1与3代表通道,通道的概念之前课程有提到。
2.void copyTo(Mat mat);复制到一个新的Mat类,属于完全复制。
3.void convertTo(Mat dst, int type);//转换成另外一种type的数据
4.Mat clone();//克隆,属于完全复制。
5.int channels()//通道,之前课程有提到。
6.int depth();//8位,16位,24位,图像文件右键属性里都有图像的位深度。
7.bool empty();//是否为空
8.部分复制:
一般情况下只会复制Mat对象的头和指针部分,不会复制数据部分
Mat A= imread(imgFilePath);
Mat B(A) // 只复制头与指针
9.完全复制:
如果想把Mat对象的头部和数据部分一起复制,可以通过如下两个API实现
Mat F = A.clone(); 或 Mat G; A.copyTo(G);
10.cv::Mat::create的详解
Mat M;
M.create(4, 3, CV_8UC2);
M = Scalar(127,127);
8位,2通道,4行,3列。如下图。
三、Mat图像像素读写
首先包含一个头文件
#include <opencv2/imgcodecs.hpp>
1.读一个GRAY像素点的像素值(CV_8UC1)
Mat grayImg;
cvtColor(image, grayImg, COLOR_BGR2GRAY);//先转为灰度图。
Scalar intensity = img.at<uchar>(y, x);
或者 Scalar intensity = img.at<uchar>(Point(x, y));
2.读一个RGB像素点的像素值
Vec3f intensity = img.at<Vec3f>(y, x);
float blue = intensity.val[0];
float green = intensity.val[1];
float red = intensity.val[2];