初探opencv——对像素进行操作(像素值取反、图片混合)

像素的操作

对像素进行操作,我们自然想到首先要提取像素点,上一篇文章中我们利用了Mat对象的ptr()函数可以返回一个指针类型的像素点,但是对指针进行操作似乎总是不和我们的常规,感觉有些危险。。。所以这篇文章主要用到at()函数

关于at():
at<template>(i,j) 代表读取某Mat对象的 i 行 j 列像素点,且返回值可变,不牵涉指针操作。
示例如下:

1.对图像的像素值进行反差

这个操作牵涉到图片的色彩空间,如果图片是三维,即rgb色彩空间,那么像素点数据类型不为uchar,而应该是Vec3b或Vec3f。(Vec3b对应 bgr的uchar类型、Vec3f对应 bgr的float类型)

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

using namespace cv;
using namespace std;

int main(int argc, char** argv) {
	Mat src = imread("E:/images/timg.jpg");
	if (src.empty()) {
		cout << "could not be found" << endl;
		return -1;
	}
	namedWindow("output", CV_WINDOW_AUTOSIZE);
	imshow("output", src);
	
	Mat dst;
	dst.create(src.size(), src.type()); // 用到了上一篇文章中的构造函数
	int nc = src.channels();
	cout << nc << endl;
	
	// 对src进行反差  即三维色彩空间
	for (int row = 0; row < height; row++) {
		for (int col = 0; col < width; col++) {
			if (nc == 1) {
				// 对一维色彩空间进行反差
				int gray = src.at<uchar>(row, col); //获取像素值
				dst.at<uchar>(row, col) = 255 - gray;
			}
			else if (nc == 3) {
			// Vec3b对应 bgr的uchar类型
			// Vec3f对象 bgr的float类型

				int b = src.at<Vec3b>(row, col)[0]; 
				int g = src.at<Vec3b>(row, col)[1];
				int r = src.at<Vec3b>(row, col)[2];
				dst.at<Vec3b>(row, col)[0] = 255 - b;
				dst.at<Vec3b>(row, col)[1] = 255 - g;
				dst.at<Vec3b>(row, col)[2] = 255 - r;
				//dst.at<Vec3b>(row, col)[2] = 255 - r;
			}
			
		}
	}
	imshow("output3", dst);
	Mat m1 = Mat::zeros(src.size(),src.type());
	// 将CV_8UC1 转换为CV_32F  即从uchar转换为float32
	src.convertTo(m1, CV_32F);
	imshow("output4", m1);
	waitKey(0);
	return 0;
}

上面写的两个for循环可不写,因为反差实质为位运算取反,可用一个api搞定。

	//一个api搞定
	bitwise_not(src, dst);  // 反位操作  相当于位运算

2.两张图片的混合

这里的混合方法为线性混合运算(带权值)。
F ( x , y ) = a l p h a ∗ f ( x , y ) + ( 1 − a l p h a ) ∗ g ( x , y ) F(x,y) = alpha * f(x, y) + ( 1 - alpha ) * g(x ,y) F(x,y)=alphaf(x,y)+(1alpha)g(x,y)
alpha属于0-1,即代表两张图混合时哪张图占的比例更大。f(x, y)、g(x ,y)分别代表src1、src2,即混合运算的两个对象,F(x,y)代表混合后生成的图片。运算对象自然是两个图片的像素值。代码如下:

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

using namespace cv;
using namespace std;
// 图片的混合
int main(int argc, char** argv) {
	Mat src1 = imread("E:/images/0.jpg");
	Mat src2 = imread("E:/images/1.jpg");
	if (src1.empty() || src2.empty()) {
		cout << "could not be found " << endl;
		return -1;
	}
	namedWindow("output01", CV_WINDOW_NORMAL);
	imshow("output01", src1);
	namedWindow("output02", CV_WINDOW_NORMAL);
	imshow("output02", src2);
	Mat dst = Mat::zeros(src1.size(), src1.type());
	double alpha = 0.5; // 代表权重
	if (src1.cols == src2.cols && src1.rows == src2.rows && src1.type() == src2.type()) {
		addWeighted(src1, alpha, src2, 1 - alpha, 0.0, dst) ;// 像素相加  线性混合 
		// multiply(src1, src2, dst, 1.0); // 像素相乘
		namedWindow("output03", CV_WINDOW_AUTOSIZE);
		imshow("output03", dst);
	}

	waitKey(0);

	return 0;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wangbowj123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值