VS+openCV 之操作像素(下)实现简单的图像运算、图像重映射

一、实现简单的图像运算

【事前准备】准备两张大小一样的图片

【实现】

    cv::Mat image1;
	image1 = cv::imread("1.jpg");
	cv::Mat image2 = cv::imread("1.1.jpg");
	cv::Mat result;
	cv::addWeighted(image1, 0.7, image2, 0.9, 0., result);//加运算
	cv::namedWindow("AddImage");
	cv::imshow("AddImage", result);
	cv::waitKey(0);

【实现原理】二进制运算函数:提供两个输入参数,指定一个输出参数,有时需要指定加权系数(可以把其中的一个输入图像用作输出图像)。cv::add就是典型的有多种格式的函数。

// c[i]= a[i]+b[i]; 
cv::add(imageA,imageB,resultC); 
// c[i]= a[i]+k; 
cv::add(imageA,cv::Scalar(k),resultC); 
// c[i]= k1*a[i]+k2*b[i]+k3; 
cv::addWeighted(imageA,k1,imageB,k2,k3,resultC); 
// c[i]= k*a[i]+b[i]; 
cv::scaleAdd(imageA,k,imageB,resultC);

// 如果(mask[i]) c[i]= a[i]+b[i]; 
cv::add(imageA,imageB,resultC,mask); 

注:(1)使用掩码后,操作只在掩码值非空的像素上执行(掩码必须是单通道的)。

       (2)在所有场合都要使用 cv::saturate_cast 函数,以确保结果在预定 的像素值范围之内

【扩展阅读】cv::Mat也可以用普通的C++运算符

1. 重载图像运算符

        cv::addWeighted也可以写成

result = 0.7 * image1 + 0.9 * image2;

        这两种方 法都会调用 cv::saturate_cast 函数

        大部分 C++运算符都已被重载,其中包括位运算符&、 |、 ^、~和函数 min、max、abs。比较运算符和>=也已被重载,它们返回一个 8 位的二值图像。此外还有矩 阵乘法 m1*m2(其中 m1 和 m2 都是 cv::Mat 实例)、矩阵求逆 m1.inv()、变位 m1.t()、行列 式 m1.determinant()、求范数 v1.norm()、叉乘 v1.cross(v2)、点乘 v1.dot(v2),等等。 

//减色函数可以用以下代码简单地进行重写
image=(image&cv::Scalar(mask,mask,mask)) 
         +cv::Scalar(div/2,div/2,div/2); 

2.分割图像通道:我们有时需要分别处理图像中的不同通道,例如只对图像中的一个通道执行某个操作。这当 然可以通过图像扫描循环实现,但也可以使用 cv::split 函数,将图像的三个通道分别复制到 三个 cv::Mat 实例中。假设我们要把一张雨景图只加到蓝色通道中,可以这样实现:

// 创建三幅图像的向量
std::vector<cv::Mat> planes; 
// 将一个三通道图像分割为三个单通道图像
cv::split(image1,planes); 
// 加到蓝色通道上
planes[0]+= image2; 
// 将三个单通道图像合并为一个三通道图像
cv::merge(planes,result); 
//这里的 cv::merge 函数执行反向操作,即用三个单通道图像创建一个彩色图像。

二、图像重映射

【实现】

#include<opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>
#include<iostream>
#include<random>
using namespace std;
using namespace cv;
//重映射图像,创建波浪形效果
void wave(const cv::Mat& image, cv::Mat& result) {
	//映射参数
	cv::Mat srcX(image.rows, image.cols, CV_32F);
	cv::Mat srcY(image.rows, image.cols, CV_32F);
	//创建映射参数
	for (int i = 0; i < image.rows; i++) {
		for (int j = 0; j < image.cols; j++) {
			//(i,j)像素的新位置
			srcX.at<float>(i, j) = j;//保持在同一列
									 //原来在第i行的像素,现在根据一个正弦曲线移动
			srcY.at<float>(i, j) = i + 5 * sin(j / 10.0);
		}
	}
	//应用映射参数
	cv::remap(image,			//源图像
			  result,			//目标图像
			  srcX,				//x映射
			  srcY,				//y映射
			  cv::INTER_LINEAR);//填补方法
}
int main()
{
	cv::Mat image;
	image = cv::imread("1.jpg");
	cv::Mat result;
	wave(image, result);
	cv::namedWindow("WaveImage");
	cv::imshow("WaveImage", result);
	cv::waitKey(0);
}

【实现原理】

        先创建映射参数,x方向和y方向,通过对x和y坐标的操作,可以形成波浪大小。

        调用remap函数,即可生成结果图像。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值