反色就是把图片上每个像素点的颜色取反,对于彩色图像,每个像素点有RGB三色,求255与每个分量的差值,即是反色。反色有照片底片的效果。
遍历图片上的每个像素点:
第一种方法:
for(int j = 0;j<srcImage.rows;j++){
for(int i = 0;i<srcImage.cols;i++){
srcImage.at<Vec3b>(j,i)[0] = 255 - srcImage.at<Vec3b>(j,i)[0];
srcImage.at<Vec3b>(j,i)[1] = 255 - srcImage.at<Vec3b>(j,i)[1];
srcImage.at<Vec3b>(j,i)[2] = 255 - srcImage.at<Vec3b>(j,i)[2];
}
}
srcImage为读入的图像,srcImage.rows是图像的行数,srcImage.cols是图像的列数,对于彩色图像,通道数是3,每一列又分BGR三个分量。
这种方法遍历每一个像素看着很直观,也很好理解,不过遍历速度太慢。下面一种方法用指针遍历:
int rowNum = srcImage.rows;//要处理的行数
int colNum = srcImage.cols * srcImage.channels();//要处理的列数
for(int j = 0;j<rowNum;j++){
uchar * row = srcImage.ptr<uchar>(j);
for(int i = 0;i<colNum ;i++){
row[i] = 255 - row[i];
}
}
srcImage.channels()返回图像的通道数,彩色图像是3,灰度图像是1.这种遍历方法能将速度提高一倍。
还有另外几种遍历图像像素的方法,下面的链接介绍了九种方法:
图像遍历
现在看一下效果图:
原图:
效果图:
完整版代码如下:
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
void fanSeFilter(Mat &srcImage);
int main(){
Mat srcImage = imread("lena.jpg");
if(!srcImage.data){
cout<<"读入图片错误!"<<endl;
return 1;
}
imshow("原图",srcImage);
fanSeFilter(srcImage);
waitKey(0);
return 0;
}
void fanSeFilter(Mat &srcImage){
int rowNum = srcImage.rows;//要处理的行数
int colNum = srcImage.cols * srcImage.channels();//要处理的列数
for(int j = 0;j<rowNum;j++){
uchar * row = srcImage.ptr<uchar>(j);
for(int i = 0;i<colNum ;i++){
row[i] = 255 - row[i];
}
}
imshow("反色滤镜",srcImage);
}