opencv入门(4)-图像操作、混合、调整

4.1 图像操作

4.1.1 读写图像

  • Mat cv::imread(const String &filename, int flags = IMREAD_COLOR)

通过imread可以指定加载为灰度或RGB图像。

  • bool cv::imwrite(const String &filename, InputArray img, const std::vector<int> &params=std::vector<int>())

通过imwrite可以保存为指定类型的图像文件。

4.1.2 读写像素

可以通过动态地址索引去获取像素值

读取单通道灰度图像(如:CV_8UC1)的某个像素点的像素值

Scalar Value=img.at<uchar>(y,x); //at直接获取位置为(行,列)
或
Scalar Value=img.at<uchar>(point(x,y));

读取三通道图像(RGB图像)的某个像素点的像素值

Vec3b Value =Img.at<Vec3b>(y,x);
uchar blue=Value[0];
uchar green=Value[1];
uchar red=Value[2];

4.1.3 像素操作示例

对图像进行像素值取反

int main()
{
	Mat srcImg = imread("D:\\testimg\\CSet12\\lena.png");
	if (srcImg.empty())
	{
		printf("Could not load the image...\n");
		return -1;
	}
	else;
	//显示窗口
	namedWindow("srcImg", WINDOW_AUTOSIZE);
	imshow("srcImg", srcImg);

	//单通道
	Mat grayImg;
	cvtColor(srcImg,grayImg,COLOR_BGR2GRAY);
	int nHeight = grayImg.rows;
	int nWidth = grayImg.cols;

	//显示窗口
	namedWindow("grayImg", WINDOW_AUTOSIZE);
	imshow("grayImg", grayImg);

	for (int i = 0; i < nHeight; i++)
	{
		for (int j = 0; j < nWidth; j++)
		{
			int grayValue = grayImg.at<uchar>(i,j);
			grayImg.at<uchar>(i, j) = 255 - grayValue;
		}
	}
	//显示窗口
	namedWindow("grayImg invert", WINDOW_AUTOSIZE);
	imshow("grayImg invert", grayImg);

    //三通道
	Mat colorInvert;
	colorInvert.create(srcImg.size(),srcImg.type());	
	int nChannels = srcImg.channels();
	if (3 == nChannels)
	{
		for (int i = 0; i < nHeight; i++)
		{
			for (int j = 0; j < nWidth; j++)
			{
				int bValue = srcImg.at<Vec3b>(i, j)[0];
				int gValue = srcImg.at<Vec3b>(i, j)[1];
				int rValue = srcImg.at<Vec3b>(i, j)[2];
				colorInvert.at<Vec3b>(i, j)[0] = 255 - bValue;
				colorInvert.at<Vec3b>(i, j)[1] = 255 - gValue;
				colorInvert.at<Vec3b>(i, j)[1] = 255 - rValue;
			}
		}
		//显示窗口
		namedWindow("srcImg invert", WINDOW_AUTOSIZE);
		imshow("srcImg invert", colorInvert);
	}
	else;


	waitKey(0);
	return 0;
}

结果图如下所示:

4.2 图像混合

4.2.1 线性混合操作

对于两个图像的线性混合可以用以下公式表征:

g(x)=(1-\alpha )*f_0(x)+\alpha* f_1(x)

其中\alpha的取值范围在0~1之间,f_0(x)f_1(x)为两张待混合的图像,g(x)为混合后的图像;

4.2.2 addWeighted函数

该函数的作用就是将两张源图片以一定的权重进行混合;

  • void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype=-1
参数含义
作用对两个图像进行加权混合,得到新的图像
输入src1

需要混合的原图1

alphasrc1的权重值
src1需要混合的原图2
betasrc2的权重值
gamma添加到每一个线性叠加总和的gamma值 
dst混合后的结果图
dtype目标图像深度,当两幅图像深度相同时可以将dtype置为-1,这样目标图像的深度将与输入图像相同
返回值void

注意事项:

  1. 需要混合的两个图像,其图像大小和类型必须一致;
  2. dst = src1*alpha + src2*beta + gamma;

4.2.3 代码示例

#include<opencv2/opencv.hpp>
#include<iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat srcImg1 = imread("D:\\testimg\\CSet12\\lena.png");
	Mat srcImg2 = imread("D:\\testimg\\CSet12\\House.png");
	if (srcImg1.empty())
	{
		printf("Could not load the image1...\n");
		return -1;
	}
	else;
	if (srcImg2.empty())
	{
		printf("Could not load the image2...\n");
		return -1;
	}
	else;
	//显示窗口
	namedWindow("srcImg1", WINDOW_AUTOSIZE);
	imshow("srcImg1", srcImg1);
	//显示窗口
	namedWindow("srcImg2", WINDOW_AUTOSIZE);
	imshow("srcImg2", srcImg2);


	if (srcImg1.size() == srcImg2.size() && srcImg1.type() == srcImg2.type())
	{
		Mat dst;
		double dAlpha = 0.5;
		double dBeta = 0.5;
		double dGamma = 0;
		addWeighted(srcImg1,dAlpha,srcImg2,dBeta,dGamma,dst);

		//add(srcImg1, srcImg2,dst,Mat());//进行两幅图像相加
		//multiply(srcImg1, srcImg2, dst, 1.0);//进行两幅图像相乘

		//显示窗口
		namedWindow("addWeight Img", WINDOW_AUTOSIZE);
		imshow("addWeight Img", dst);
	}
	else
	{
		printf("Could not blend image,the size or type is not same...\n");
		return -1;
	}

	waitKey(0);
	return 0;
}

结果图像(alpha=0.5,beta=0.5,gamma=0):

以下对比直接相加和相乘的差异:

 无权重相加的时候,直接相加或相乘,单个像素值的大小容易大于255,及像素点赋值255。

 4.3 图像调整(亮度和对比度)

图像变换可以分为两类(像素变换--点操作,领域操作--区域)

  1. 点运算也称为对比度增强和拉伸、灰度变换。常用于改变图像的灰度范围和分布,如光度学标定、对比度增强、显示增强、轮廓线确定、图像裁剪等。
  2. 领域操作是指输出图像的像素点取值决定于输入图像的某个像素点及其领域内的像素,通常远小于图像自身尺寸、形状规则的像素块。通常使用于图像卷积、整体特征提取、梯度计算、模式匹配前处理、模糊、角点检测等。

这里介绍的调整图像亮度和对比度属于像素变换-点操作

g(i,j)=\alpha f(i,j)+\beta 其中\alpha>0, \beta是增益变量。

4.3.1 代码示例

#include<opencv2/opencv.hpp>
#include<iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat srcImg = imread("D:\\testimg\\CSet12\\lena.png");
	if (srcImg.empty())
	{
		printf("Could not load the image...\n");
		return -1;
	}
	else;

	//显示窗口
	char input_win[] = "srcImg";
	namedWindow(input_win, WINDOW_AUTOSIZE);
	imshow(input_win, srcImg);

	//对比度和亮度调整
	int nHeight = srcImg.rows;
	int nWidth = srcImg.cols;
	Mat dst = Mat::zeros(srcImg.size(),srcImg.type());
	float fAlpha = 1.5;
	float fBeta = 10;
	for (int i = 0;i < nHeight; i++)
	{
		for (int j = 0;j < nWidth; j++)
		{
			if (3 == srcImg.channels())
			{
				float b = srcImg.at<Vec3b>(i,j)[0];
				float g = srcImg.at<Vec3b>(i, j)[1];
				float r = srcImg.at<Vec3b>(i, j)[2];

				dst.at<Vec3b>(i, j)[0] = saturate_cast<uchar>(fAlpha*b+ fBeta);
				dst.at<Vec3b>(i, j)[1] = saturate_cast<uchar>(fAlpha*g + fBeta);
				dst.at<Vec3b>(i, j)[2] = saturate_cast<uchar>(fAlpha*r + fBeta);
			}
			else if (1 == srcImg.channels())
			{
				float v = srcImg.at<uchar>(i, j);
				dst.at<uchar>(i, j) = saturate_cast<uchar>(fAlpha*v + fBeta);
			}
		}
	}

	namedWindow("contract and brightness change");
	imshow("contract and brightness change", dst);

	waitKey(0);
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值