2017-12-23 22:34:18 saltriver 阅读数 1462

我们知道2个矩阵是可以执行加法运算的,那2个图像能不能相加呢?当然是可以的。前面提到,图像就是函数,函数可以相加,图像当然也可以相加。

我们知道2个矩阵相加必须是同一维度的,即行列相同,图像当然也一样,即宽度和高度相同。

我们看下面2副图像:
这里写图片描述

这里写图片描述

import cv2
boats = cv2.imread("boats.bmp", 0)
goldhill = cv2.imread("goldhill.bmp", 0)
print(boats.shape)
print(goldhill.shape)

输出结果:

(576, 720)
(576, 720)

可以看出,这2副图像的宽度和高度分别是720和576,大小是一致的。2个图像相加就是2个矩阵相加。

unite = boats + goldhill
cv2.imshow("unite", unite)
cv2.waitKey()

输出结果:

这里写图片描述

不怎么样嘛!白块,黑块怎么那么多!有的地方变白了,有的地方变黑了。what’s wrong?

我们知道,图像的强度取值区间是[0, 255],opencv的图像类型是uint8类型。而numpy的矩阵加法是一种模(mod)操作,即200+60=260 % 256 = 4,所以该亮的地方反而暗淡了。

opencv自带有图像加法操作运算函数:add(x, y)。add使用的是饱和操作,即200+60=260->255。所以使用opencv自带的add()函数效果会更好。

另外,2副图像相加,我们实际上需要的2副图像相对位置强度的平均值,因此在相加前,需要各除以2,然后再相加(注意要整除)。

unite = cv2.add(boats // 2 , goldhill // 2)
cv2.imshow("unite", unite)
cv2.waitKey()

这里写图片描述

我们知道,除以2和乘以0.5是等价的。乘以0.5是一个数乘运算,也就是说,图像自身还可以进行这种运算(注意乘以浮点数后矩阵类型发生了改变,而opencv的图像矩阵必须转换成为uint8类型才能正常显示)。

boats20 = 0.2 * boats
boats20 = boats20.astype("uint8")
cv2.imshow("boats20", boats20)
cv2.waitKey()

输出结果:
这里写图片描述

可以看到,整体效果暗淡了很多。因为所有的像素点的值都乘以了0.2,强度变成了原来的20%。如果乘的数值小于1,图像整体就变暗,如果乘的数值大于1,整体就变亮。

这给了我们混合2张图像的一种比率调和方法,例如最前面2张图,我们想要看到更多的船(注意为确保2张图像的混合值小于255,系数之和应保持等于1)。

unite = 0.75 * boats + 0.25 * goldhill
unite = unite.astype("uint8")
cv2.imshow("unite", unite)
cv2.waitKey()

这里写图片描述

当然,opencv已经为我们准备好了函数addWeighted
()。代码如下,效果是一样的。

unite = cv2.addWeighted(boats, 0.75, goldhill, 0.25, 0)
cv2.imshow("unite", unite)
cv2.waitKey()

那么:图像为什么要相加呢?为了混合(blend)2张图像。

实质上,图像相加还有一个用途:降噪。同一场景的不同时间采集图像通过相加平均后去除噪声,这个后面再讲。

2017-02-18 15:24:44 qq_34784753 阅读数 23944

看完了数字图像处理后,从头开始使用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;
}





2019-05-31 17:16:26 qq_36958831 阅读数 26

主要是对彩色图像进行线性相加(融合)

难点:1.相加之后数值大于256处理:np.uint8
2.对于三通道的理解,三维矩阵的构造
3.代码比较简单,运行速度较慢

img1=np.asanyarray((img1))
img2=np.asanyarray((img2))
w,h,c=img1.shape
img3=np.zeros((w,h,c))
a=0.4
b=0.7
for i in range(w-1):
    for j in range(h-1):
        print(img1[i,j,0])
        img3[i,j,0]=float(img1[i,j,0]*a)+float(img2[i,j,0]*b)
        img3[i, j,1] = float(img1[i, j, 1] * a) + float(img2[i, j, 1] * b)
        img3[i, j,2] = float(img1[i, j, 2] * a) + float(img2[i, j, 2] * b)
cv2.imshow('img3',np.uint8(img3))
#cv2.imshow('img1',img1)
cv2.waitKey(0)
cv2.destroyAllWindows()

融合后的图像

2018-11-02 21:58:17 weixin_42145502 阅读数 90

1、彩色图像处理

1.1伪彩色处理

对于不同的灰度或灰度范围赋予不同的颜色
伪彩色处理是将灰度图像转化为彩色图像;
目的:由于人眼对彩色的分辨能力远远超过对灰度的分辨能力,为了提高人眼对图形的细节分辨能力,所以将灰度图像转化为彩色图像表示,一达到图像增强的目的。

1.2三原色原理(HSI模型)

其基本内容:
任何颜色都可以用3种不同的基本颜色按照不同的比例混合得到。原色相加可以得到二次色。例如:红+黑=深红;红+蓝=青;红+绿=黄;红+绿+蓝=白
下图就是RGB模型:
在这里插入图片描述在这里插入图片描述

1.3彩色基础

区分颜色常用三种基本的特性量
亮度、色调、饱和度

1.4HSI模型

H【色调】表示颜色,颜色与彩色光的柏长波有关,色调的取值用角度表示
S【饱和度】表示色的纯度,也就是彩色光的掺杂白光程度。白光越多饱和度越低,白光越少饱和度越高且颜色越纯
I【强度】表示人眼感受彩色光的强弱程度,它与彩色光的能量大小有关。
主要基于两个重要的事实:
(1)I分量与图像的彩色信息无关
(2)H与S分量与人的感受颜色的方式精密相关。
!](https://img-blog.csdnimg.cn/20181102214947888.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjE0NTUwMg==,size_16,color_FFFFFF,t_70)
在这里插入图片描述
从RGB到HSI的变换是一个非线性变换
在这里插入图片描述

2015-12-11 13:45:26 smbzy 阅读数 740

可以使用OpenCV的cv::addWeighted函数来进行两张图片的相加处理。两张图片进行相加,其原理相当于是表示图像的两个矩阵进行相加,那么这时应该注意的是:既然是矩阵相加,那么矩阵的行和列也要求相对应吧,所以两张加载的图片的尺寸必须是一样的,不然的话就会出现错误。

代码实现:

#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;

int main()
{
    cout<<"add Image:"<<endl;
    cv::Mat ahead=cv::imread("./images/canal1.jpg");
    if(!ahead.data)
        cout<<"ahead image load fail"<<endl;
    cv::Mat behide=cv::imread("./images/boldt.jpg");
    if(!behide.data)
        cout<<"behide image load fail"<<endl;
    double alpha=0.7;
    double beta=0.9;
    cv::namedWindow("fix Image",1);
    cv::Mat result;
    cv::addWeighted(ahead,alpha,behide,beta,0,result);
    cv::imshow("show fixedImage",result);
    cv::waitKey(0);
    return 0;
}


结果:


原始图像:





没有更多推荐了,返回首页