No1. 基于OpenCV的图像编程基础


主要内容

1、配置基于VS2017和OpenCV3.1.0的编程环境。
2、 读入、显示及存储图像。
3、 编写三种遍历扫描整幅图像的方法,对灰度图像增强亮度,对彩色图像加入300个椒盐噪声,以此掌握如何操作像素。
4、对彩色图像增加亮度。


一、配置编程环境

1. 下载安装包

在官网

https://sourceforge.net/projects/opencvlibrary/

下载OpenCV3.1.0的安装包。

2. 解压文件

打开压缩包,按照提示安装在路径“D:\opencv”下。

OpenCV3.1.0安装包解压后的文件

3. 配置环境变量

在设置的搜索框中搜索“环境变量”,并选择“编辑系统环境变量”。系统设置的搜索界面
环境变量设置界面

编辑Path,弹出对话框后,点击新建。

Path的位置
输入OpenCV安装解压后的路径后点击完成。
添加路径

4. 配置编译器

依此点击【文件】→【新建】→【项目】→【控制台应用程序】,结果如下图所示:
新建控制台文件界面
右击工程文件夹,选择属性,结果如图所示:
图片
在【VC++目录】→【包含目录】→【编辑】下添加三条路径

D:\opencv\build
D:\opencv\build\include\opencv
D:\opencv\build\include\opencv2

在这里插入图片描述
在【VC++目录】→【库目录】→【编辑】下添加一条路径

D:\opencv\build\x64\vc14\lib

在这里插入图片描述
在【连接器】→【附加依赖项】→【编辑】下添加两个文件

opencv_world310d.lib
opencv_world310.lib

点击完成则配置完成
在这里插入图片描述

二、OpenCV读入、显示、存储图像的相关函数

首先需要定义一个用于储存图像的变量,在OpenCV中,通过定义从cv::Mat类的对象来实现。

cv::Mat image;

1. 读入图片

调用imread()函数可以读取图像文件,该函数读入文件图像并对其经行编码,分配内存,例如:

image = cv::imread(“E://test1//pepper.bmp”);

2. 显示图片

需要调用cv::namedWindow()创建一个显示窗口,例如:

cv::namedWindow(“Original Image”);

调用cv::imshow()来显示图像,例如:

cv::imshow(“Original Image”,image);

3. 储存图片

调用cv::imwrite()函数存储处理后的图像,例如:

cv::imwrite(“E://test1//output.bmp”,result);

三、遍历图像数据的方法

1. at方法

cv::Mat提供了一个at(int y, int x)函数模板来操作指定位置的矩阵元素,在使用时需要指定函数返回的数据类型,例如:

image.at<unchar>(j,i)=255;
//采用嵌套循环的方式便可以实现遍历,代码示例如下:
void light(Mat& inputImage, Mat& outputImage, int add) 
{
	int i, j;
	outputImage = inputImage.clone();
	int rows = outputImage.rows;
	int cols = outputImage.cols;
	for ( i = 0; i < rows; i++) {
		for ( j = 0; j < cols; j++) {
			outputImage.at<Vec3b>(i,j)[0] = saturate_cast<uchar>(outputImage.at<Vec3b>(i, j)[0] +add);
		 	outputImage.at<Vec3b>(i,j)[1] = saturate_cast<uchar>(outputImage.at<Vec3b>(i, j)[1] +add);
			outputImage.at<Vec3b>(i,j)[2] = saturate_cast<uchar>(outputImage.at<Vec3b>(i, j)[2] +add);
		}
	}
}

2. 使用迭代器

类似于STL库的使用方法,OpenCV可以采用迭代器实现对像素的操作,代码示例如下:

void light (Mat& inputImage, Mat& outputImage, int add)
{
	outputImage = inputImage.clone();
	Mat_<Vec3b>::iterator it = inputImage.begin<Vec3b>();
	Mat_<Vec3b>::iterator itend = inputImage.end<Vec3b>();
	Mat_<Vec3b>cimage = outputImage;
	Mat_<Vec3b>::iterator itout = cimage.begin();
	Mat_<Vec3b>::iterator itoutend = cimage.end();

	for (; it != itend; it++,itout++) {
		(*itout)[0] = saturate_cast<uchar>((*it)[0] + add);
		(*itout)[1] = saturate_cast<uchar>((*it)[1] + add);
		(*itout)[2] = saturate_cast<uchar>((*it)[2] + add);
	}
}

3. 使用指针

cv::Mat提供一个print(int i)函数模板来获取指定行数据的首地址。利用这一地址可以实现对像素的操作。代码示例如下:

void light(Mat& inputImage, Mat& outputImage, int add)
{
	int i, j;
	outputImage = inputImage.clone();
	int rows = outputImage.rows;
	int cols = outputImage.cols * outputImage.channels();
	for (i = 0; i < rows; i++) {
		uchar * data = inputImage.ptr<uchar>(i);
		uchar * dataout = outputImage.ptr<uchar>(i);
		for (j = 0; j < cols; j++) {
			dataout[j] = saturate_cast<uchar>(dataout[j]+add);
		}
	}
}

四、增加色彩亮度

为了增加彩色图的亮度,需要先遍历每个像素点。三个通道加上一个相同的数值即可,提高亮度。


五、结果分析

1. 读入、显示及存储图像

这里读入了一张图片,并将它经行轴对称变换,显示并储存。代码如下:

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
	Mat image, result;
	cout << "size:" << image.size().height << "," << image.size().width << endl;
	image = imread("E://test1//pepper.bmp");
	if (!image.data) {
		//检查是否读取图像
		cout << "Error! Input image cannot be read...\n";
	}
	namedWindow("Original Image");
	imshow("Original Image", image);
	flip(image, result, 1);
	namedWindow("Output Image");
	imshow("Output Image", result);
	imwrite("E://test1//output.bmp", result);
	waitKey(0); // Wait for key press
	return 0;
}

图像对称变换

图像对称变换
处理后的图片储存的相应的文件夹下

处理后的图片储存的相应的文件夹下

2. 遍历图像

这里以使用迭代器的方法为例子,对灰度图像增加亮度,即为像素点的单通道增加一个定值,代码示例如下(这里使用了saturate_cast()函数作为溢出保护,防止图片失真):

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui.hpp>
using namespace std;
using namespace cv;
void colourReduce(Mat& inputImage, Mat& outputImage, int add)
{
	    outputImage = inputImage.clone();
	    Mat_<Vec3b>::iterator it = inputImage.begin<Vec3b>();
	    Mat_<Vec3b>::iterator itend = inputImage.end<Vec3b>();
	    Mat_<Vec3b>cimage = outputImage;
	    Mat_<Vec3b>::iterator itout = cimage.begin();
	    Mat_<Vec3b>::iterator itoutend = cimage.end();
	    for (; it != itend; it++,itout++) {
		    (*itout)[0] = saturate_cast<uchar>((*it)[0] + add);
		    (*itout)[1] = saturate_cast<uchar>((*it)[1] + add);
		    (*itout)[2] = saturate_cast<uchar>((*it)[2] + add);
	     }
}
int main()
{
	    Mat in_image, out_image;
	    in_image = imread("E://test2.2//cameraman.jpg");
	    if (!in_image.data) {
		   //检查是否读取图像
		  cout << "Error! Input image cannot be read...\n";
	 }
	namedWindow("Original Image");
	imshow("Original Image", in_image);
	colourReduce(in_image, out_image, 100);
	namedWindow("Output Image");
	imshow("Output Image", out_image);
	imwrite("E://test2.2//outputImage2.1.jpg", out_image);
	waitKey(0); // Wait for key press
	return 0;
}

结果为增加灰度图的亮度
增加灰度图的亮度
椒盐噪声是指两种噪声:盐噪声和椒噪声。盐噪声一般是白色噪声,椒噪声一般是黑色噪声。前者属于高灰度噪声,或者属于低灰度噪声,一般两种噪声同时出现,呈现黑白杂点。
对彩色图像加入300个椒盐噪声。即在随机的行和列上,将通道的值设为255或0,这里使用at方法进行遍历,示例代码如下:

 void addsaltnoise(Mat& inputImage, Mat& outputImage, int n)
{
	int m,f;
	outputImage = inputImage.clone();
	for (m = 0; m < n; m++) {
		int i = rand() % outputImage.rows;
		int j = rand() % outputImage.cols;
		f = rand() % 2;
		if (f == 0) {
			outputImage.at<Vec3b>(i, j)[0] = 255;  //添加盐噪声
			outputImage.at<Vec3b>(i, j)[1] = 255;
			outputImage.at<Vec3b>(i, j)[2] = 255;
		}
		else {
			outputImage.at<Vec3b>(i, j)[0] = 0;  //添加椒噪声
			outputImage.at<Vec3b>(i, j)[1] = 0;
			outputImage.at<Vec3b>(i, j)[2] = 0;
		}	
	}

结果为插入300个椒盐点后的图片

插入300个椒盐点后的图片

3. 对彩色图像增加亮度

对彩色图增加亮度,即为三个通道各加上一个定值,这里用at方法进行遍历,示例代码如下:

void light(Mat& inputImage, Mat& outputImage, int add)
{
	int i, j;
	outputImage = inputImage.clone();
	int rows = outputImage.rows;
	int cols = outputImage.cols;
	for (i = 0; i < rows; i++) {
		for (j = 0; j < cols; j++) {
			outputImage.at<Vec3b>(i,j)[0]= saturate_cast<uchar>(outputImage.at<Vec3b>(i, j)[0] + add);
			outputImage.at<Vec3b>(i,j)[1]=
saturate_cast<uchar>(outputImage.at<Vec3b>(i, j)[1] + add);
			outputImage.at<Vec3b>(i,j)[2]= saturate_cast<uchar>(outputImage.at<Vec3b>(i, j)[2] + add);
		}
	}
}

结果为增加亮度后的彩色图
增加亮度后的彩色图

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值