Mat矩阵中每一个元素代表一个像素,灰度图像,像素用8U 无符号数,0黑色,255白色;彩色图像,每个像素需要3位这样的8U表示,即三个通道(R、G、B),矩阵依次存储一个像素的三个通道值,然后再存储下一个像素点。
灰度图像素类型uchar; 彩色图像素点类型Vec3b
计时
double time0 = static_cast<double>(getTickCount()); { } time0 = ((double)getTickCount()-time0)/getTickFrequency();压缩颜色空间
在一幅数字图像存储的矩阵一般是uchar类型,为8位256个值。如果是三通道图形,那么应该有256*256*256=16581375种不同的颜色,这1600多万种颜色,数据量会很大,影响后期的处理,这个时候,我们就需要将颜色空间进行缩减。
对于三通道图像,本来有256*256*256种颜色,这里我们取:
0-9的像素取值:0
10-19的像素取值:1
……
250-256的像素取值:25
本节对应数学表达公式:I(x,y)= I(x,y)/div *div + div/2;
主程序
#include<opencv2/opencv.hpp> #include<iostream> using namespace cv; using namespace std; //颜色空间缩减函数 void colorreduce(Mat& input, Mat& output, int div); int main() { //原图像 Mat src = imread("dota.png"); imshow("原图像", src); //生成图像 Mat dest; dest.create(src.rows, src.cols, src.type()); //颜色缩减 double time0 = static_cast<double>(getTickCount()); colorreduce(src, dest, 64); time0 = ((double)getTickCount() - time0) / getTickFrequency(); cout << "运行时间" << time0 << "秒" << endl; imshow("生成图像", dest); waitKey(); return 0; }提供ptr函数访问任意一行像素的首地址,特别方便图像的一行一行的横向访问。
速度很快。
//获取像素指针 uchar * p = output.ptr<uchar>(i); Vec3b * p = output.ptr<Vec3b>(i);void colorreduce(Mat& input, Mat& output, int div) { output = input.clone(); int row = input.rows; int cols = input.cols*input.channels();//每一行元素个数 for (int i = 0; i < row; i++) { //需要在output上进行更改 uchar* data = output.ptr<uchar>(i); for (int j = 0; j < cols; j++) { data[j] = data[j] / div*div + div / 2; } } }
或者
//彩色图 for (int i = 0; i < colorim.rows; ++i) { //获取第 i 行首像素指针 Vec3b * p = colorim.ptr<Vec3b>(i); for (int j = 0; j < colorim.cols; ++j) { //三通道 p[j][0] = i % 255; //Blue p[j][1] = j % 255; //Green p[j][2] = 0; //Red } }3、 用动态地址计算配合at访问像素
void colorReduce(Mat& inputImage, Mat& outputImage, int div) { outputImage = inputImage.clone(); int rowNumber = outputImage.rows; int colNumber = outputImage.cols; for (int i = 0; i < rowNumber; i++) { for (int j = 0; j < colNumber; j++) { outputImage.at<Vec3b>(i, j)[0] = outputImage.at<Vec3b>(i, j)[0] / div*div + div / 2; //蓝色通道 outputImage.at<Vec3b>(i, j)[1] = outputImage.at<Vec3b>(i, j)[1] / div*div + div / 2; //绿色通道 outputImage.at<Vec3b>(i, j)[2] = outputImage.at<Vec3b>(i, j)[2] / div*div + div / 2; //红色通道 } } }