OpenCV 访问图像中的像素|颜色空间缩减


在OpenCV中,提供了三种访问每个像素的方法。

  • 方法一指针访问:C操作符[];
  • 方法二迭代器iterator;
  • 方法三动态地址计算。
#include 
#include 
#include 

using namespace cv;
using namespace std;


/*指针访问:C 操作符[]*/
void colorReduce1(Mat& inputImage, Mat& outputImage, int div)
{
    outputImage = inputImage.clone();
    int rowNumber = outputImage.rows; // 行数
    int colNumber = outputImage.cols * outputImage.channels(); // 列数 x 通道数 = 每一行元素个数

    // 双循环遍历所有像素
    for (int i = 0; i < rowNumber; i++) {
        uchar* data = outputImage.ptr(i); // 获取 i 行首地址

        // 列循环
        for (int j = 0; j < colNumber; j++) {
            data[j] = (data[j] / div) * div + div / 2;
            // 也可以
            //*data++ = (*data / div) * div + div / 2;
        }
    }
}

/*用迭代器操作像素*/
void colorReduce2(Mat& inputImage, Mat& outputImage, int div)
{
    outputImage = inputImage.clone();

    // 获取迭代器
    Mat_::iterator it = outputImage.begin(); //初始位置迭代器
    Mat_::iterator itend = outputImage.end(); // 终止位置迭代器

    for (; it != itend; it++) {
        // 处理开始
        (*it)[0] = ((*it)[0] / div) * div + div / 2;
        (*it)[1] = ((*it)[1] / div) * div + div / 2;
        (*it)[2] = ((*it)[2] / div) * div + div / 2;
        // 处理结束
    }
}

/*动态地址计算*/
void colorReduce3(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 < rowNumber; j++) {
            // 处理开始
            // 蓝色通道
            outputImage.at(i, j)[0] = (outputImage.at(i, j)[0] / div) * div + div / 2;
            // 绿色通道
            outputImage.at(i, j)[1] = (outputImage.at(i, j)[1] / div) * div + div / 2;
            // 红色通道
            outputImage.at(i, j)[2] = (outputImage.at(i, j)[2] / div) * div + div / 2;
            // 处理结束
        }
    }
}


int main(int argc, char ** argv)
{
    Mat srcImage = imread(".//image5.1//1.jpg");
    imshow("原图", srcImage);

    Mat dstImage1;
    Mat dstImage2;
    Mat dstImage3;
    dstImage1.create(srcImage.rows, srcImage.cols, srcImage.type()); // 效果图的大小与原始图的大小类型相同
    dstImage2.create(srcImage.rows, srcImage.cols, srcImage.type()); // 效果图的大小与原始图的大小类型相同
    dstImage3.create(srcImage.rows, srcImage.cols, srcImage.type()); // 效果图的大小与原始图的大小类型相同

    // 记录起始时间
    double time0 = static_cast(getTickCount()); 
    // 调用缩减函数1
    colorReduce1(srcImage, dstImage1, 32);  // 256 / 32 = 8
    time0 = ((double)getTickCount() - time0) / getTickFrequency();
    cout << "指针访问:C操作符[]运行时间为:" << time0 << "秒" << endl;
    imshow("效果图1", dstImage1);   

    time0 = static_cast(getTickCount());

    // 调用缩减函数2
    colorReduce2(srcImage, dstImage2, 32);  // 256 / 32 = 8
    time0 = ((double)getTickCount() - time0) / getTickFrequency();
    cout << "迭代器操作,运行时间为:" << time0 << "秒" << endl;
    imshow("效果图2", dstImage2);

    time0 = static_cast(getTickCount());

    // 调用缩减函数2
    colorReduce3(srcImage, dstImage3, 32);  // 256 / 32 = 8
    time0 = ((double)getTickCount() - time0) / getTickFrequency();
    cout << "动态地址计算,运行时间为:" << time0 << "秒" << endl;
    imshow("效果图3", dstImage3);

    waitKey(0);
    return(0);
}

运行 3 次时间对比:

指针访问:C操作符[]运行时间为:0.002704秒
迭代器操作,运行时间为:0.0986663秒
动态地址计算,运行时间为:0.0809037秒
指针访问:C操作符[]运行时间为:0.0028266秒
迭代器操作,运行时间为:0.0972075秒
动态地址计算,运行时间为:0.0750282秒
指针访问:C操作符[]运行时间为:0.0027457秒
迭代器操作,运行时间为:0.0951924秒
动态地址计算,运行时间为:0.0748235秒

图像输出:




参考:

《OpenCV3 编程入门》 毛星云 P111