对像素进行操作,我们自然想到首先要提取像素点,上一篇文章中我们利用了Mat对象的ptr()函数可以返回一个指针类型的像素点,但是对指针进行操作似乎总是不和我们的常规,感觉有些危险。。。所以这篇文章主要用到at()函数
关于at():
at(i,j) 代表读取某Mat对象的 i 行 j 列像素点,且返回值可变,不牵涉指针操作。
示例如下:
1.对图像的像素值进行反差
这个操作牵涉到图片的色彩空间,如果图片是三维,即rgb色彩空间,那么像素点数据类型不为uchar,而应该是Vec3b或Vec3f。(Vec3b对应 bgr的uchar类型、Vec3f对应 bgr的float类型)
#include
#include
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(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)=alpha∗f(x,y)+(1−alpha)∗g(x,y)
alpha属于0-1,即代表两张图混合时哪张图占的比例更大。f(x, y)、g(x ,y)分别代表src1、src2,即混合运算的两个对象,F(x,y)代表混合后生成的图片。运算对象自然是两个图片的像素值。代码如下:
#include
#include
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;
}