OpenCV C++开发 第二节:图像处理(三、图像对比度提升、Mat对象详解、Mat图像像素读写)

13 篇文章 6 订阅

一、图像对比度提升(掩膜操作)

#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.掩膜操作。这是提高图像对比度的一种方法,根据掩膜重新计算每个像素的像素值。

先看公式:

\mathbf{I(i,j)=5*I(i,j)-[I(i-1,j)+I(i+1,j)+I(i,j-1)+I(i,j+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];

博客还会继续更新。同学们可以互相交通沟流、互相提升。这是我的qq群:608958953。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值