【OpenCV图像处理】一、图像相加、相减、相乘与相除的实现

看完了数字图像处理后,从头开始使用opencv进行相关内容的实现,使用的环境是VS2013+OpenCV2.4.9

1.图像的加运算

加运算就是两幅图像对应像素的灰度值或彩色分量进行相加。主要有两种用途,一种是消除图像的随机噪声,主要做是讲同一场景的图像进行相加后再取平均;另一种是用来做特效,把多幅图像叠加在一起,再进一步进行处理。

对于灰度图像,因为只有单通道,所以直接进行相应位置的像素加法即可,对于彩色图像,则应该将对应的颜色的分量分别进行相加。

通常来将,两幅或多幅相加的图像的大小和尺寸应该相同。

以下为代码部分,使用了两种方法进行实现,一是使用迭代器进行图像的遍历进行相加,另一种是使用OpenCV中的addWeighted函数进行线性相加。

经过师兄提醒,在这里补充一下,在OpenCV中除了上述使用函数的方法外,还可以直接运用运算符进行操作,例如在求两个图像的和的时候,可以直接写为

result1 = (img1 + img2) / 2;
在进行二值化时,再将图像灰度化后,可以直接使用类似语句

result = (img1 > 30);

在实际的使用中,灵活的运用运算符进行图像的操作可以带来很大的方便。


PS:再次感谢师兄的提醒 :D 




//本程序实现将两张尺寸相同的图像进行相加
//在对像素进行操作时,使用的时迭代器的方法
//2017-02-18

#include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>

using namespace cv;
using namespace std; 

int main()
{
	Mat img1, img2, result1;
	img1 = imread("1234.jpg");
	img2 = imread("2345.jpg");
	result1 = img1.clone();
	Mat_<Vec3b>::iterator it = result1.begin<Vec3b>();	//result1初始位置的迭代器
	Mat_<Vec3b>::iterator itend = result1.end<Vec3b>();	//result1终止位置的迭代器
	Mat_<Vec3b>::iterator it1 = img1.begin<Vec3b>();   //img1初始迭代器
	Mat_<Vec3b>::iterator it2 = img2.begin<Vec3b>();	//img2初始迭代器
	//进行遍历
	for (; it != itend; it++)
	{
		(*it)[0] = ((*it1)[0] + (*it2)[0]) /2;
		(*it)[1] = ((*it1)[1] + (*it2)[1]) /2;
		(*it)[2] = ((*it1)[2] + (*it2)[2]) /2;
		it1++;
		it2++;
	}
	namedWindow("原图1",1);
	imshow("原图1", img1);
	namedWindow("原图2", 0);
	imshow("原图2", img2);
	namedWindow("相加后的图像",0);
	imshow("相加后的图像", result1);
	Mat result2 = result1.clone();
	addWeighted(img1, 1, img2, 1, 0,result2);
	namedWindow("addWeighted");
	imshow("addWeighted", result2);
	waitKey();
	return 0;
}


运行结果为:




2.图像相减

减法运算就是两幅图像见对象像素的灰度值或彩色分量进行相减,它可以用于目标检测,程序实现还是使用两种方法。

以下为程序部分

//本程序实现两个尺寸相同的图像进行相减的操作
//分别使用遍历像素的方法和addWeighted的方法

#include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>

using namespace std;
using namespace cv;
uchar toZero(uchar a);//置零函数,小于零则为0
int main()
{
	Mat imag1, imag2, result1, result2;
	imag1 = imread("2345.jpg");
	imag2 = imread("1234.jpg");
	result1 = imag1.clone();
	result2 = imag2.clone();
	
	int rowNumber = result1.rows;
	int colNumber = result1.cols;
	for (int i = 0; i < rowNumber; i++)
	{
		for (int j = 0; j < colNumber; j++)
		{
			result1.at<Vec3b>(i, j)[0] = toZero(imag1.at<Vec3b>(i, j)[0] - imag2.at<Vec3b>(i, j)[0]);
			result1.at<Vec3b>(i, j)[1] = toZero(imag1.at<Vec3b>(i, j)[1] - imag2.at<Vec3b>(i, j)[1]);
			result1.at<Vec3b>(i, j)[2] = toZero(imag1.at<Vec3b>(i, j)[2] - imag2.at<Vec3b>(i, j)[2]);
		}
	}
	//addWeighted方法进行图像相减
	addWeighted(imag1, 1, imag2, -1, 0,result2);
	imshow("原图1", imag1);
	imshow("原图2", imag2);
	imshow("result1", result1);
	imshow("addWeighted", result2);
	waitKey();
	return 0;
}

uchar toZero(uchar a)
{
	if (a < 0)
		return 0;
	else
		return a;
}


运行结果为:


result1貌似有问题,需要进一步进行检查。


3.图像相乘

图像的乘法运算就是将两幅图像对应的灰度值或彩色分量进行相乘。

乘运算的主要作用是抑制图像的某些区域,掩膜值置为1,否则置为0。乘运算有时也被用来实现卷积或相关的运算。

以下为相关程序代码。


//图像的乘运算。
//将两幅图像对应的灰度值或彩色分量进行相乘。

#include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>

using namespace std;
using namespace cv;

int main()
{
	Mat imag1, imag2, result;
	imag1 = imread("1234.jpg");
	imag2 = imread("2345.jpg");
	result = imag1.clone();
	int rowNumber = result.rows;
	int colNumber = result.cols;
	for (int i = 0; i < rowNumber; i++)
	{
		for (int j = 0; j < colNumber; j++)
		{
			result.at<Vec3b>(i, j)[0] = (imag1.at<Vec3b>(i, j)[0] * imag2.at<Vec3b>(i, j)[0]) % 256;
			result.at<Vec3b>(i, j)[1] = (imag1.at<Vec3b>(i, j)[1] * imag2.at<Vec3b>(i, j)[1]) % 256;
			result.at<Vec3b>(i, j)[2] = (imag1.at<Vec3b>(i, j)[2] * imag2.at<Vec3b>(i, j)[2]) % 256;
		}
	}
	imshow("原图1", imag1);
	imshow("原图2", imag2);
	imshow("相乘后的图像", result);
	waitKey();
	return 0;
}

实验的结果如下:



4.图像相除

图像除运算就是两幅图像对应像素的灰度值或彩色分量进行相除。

简单的出运算可以用于改变图像的灰度级


以下为代码部分


//图像的除法运算
//就是讲两幅图像的对应像素的灰度值或彩色分量进行相除。
//简单的除运算可以用来改变图像的灰度级。

#include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>

using namespace std;
using namespace cv;

int main()
{
	Mat imag1, imag2, result;
	imag2 = imread("1234.jpg");
	imag1 = imread("2345.jpg");
	result = imag1.clone();

	int rowNumber = result.rows;
	int colNumber = result.cols;
	for (int i = 0; i < rowNumber; i++)
	{
		for (int j = 0; j < colNumber; j++)
		{
			result.at<Vec3b>(i, j)[0] = (imag1.at<Vec3b>(i, j)[0] * 1.0) / imag2.at<Vec3b>(i, j)[0];
			result.at<Vec3b>(i, j)[1] = (imag1.at<Vec3b>(i, j)[1] * 1.0) / imag2.at<Vec3b>(i, j)[1];
			result.at<Vec3b>(i, j)[2] = (imag1.at<Vec3b>(i, j)[2] * 1.0) / imag2.at<Vec3b>(i, j)[2];
		}
	}
	imshow("原图1", imag1);
	imshow("原图2", imag2);
	imshow("相除后的图像", result);
	waitKey();
	return 0;
}





评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值