zoukankan      html  css  js  c++  java
  • OpenCV几种不同的图像遍历方法分析与对比

    学习《OpenCV2计算机视觉编程手册》第二章的学习体会

    关键词:图像处理-图像变换-点运算-图像遍历-淡化像素

    首先,看一下的基础代码,实现了图片遍历淡化每个像素;

    void main()
    {    
        Mat image = imread("lena.jpg");
        namedWindow("Image");
        
        colorReduce1(image);
        
        imshow("Image", image);
    
        waitKey(0);
    
    }
    void colorReduce1(Mat &image, int div = 64) //time=2.43ms
    {
        int n1 = image.rows;
        int nc = image.cols*image.channels();
        for (int j = 0; j < n1; j++)
        {
            uchar* data = image.ptr<uchar>(j);
            
            for (int i = 0; i < nc; i++)
            data[i] = data[i] / div*div + div / 2;//(data[i]/div)*div
        }
    
    }

    书中给了多个图像遍历的方法,附上全部代码,代码如下:

    #include <opencv2opencv.hpp>  
    #include<iostream>
    using namespace cv;
    
    void colorReduce1(Mat &image, int div = 64) //time=2.43ms
    {
        int n1 = image.rows;
        int nc = image.cols*image.channels();
        for (int j = 0; j < n1; j++)
        {
            uchar* data = image.ptr<uchar>(j);
            
            for (int i = 0; i < nc; i++)
            data[i] = data[i] / div*div + div / 2;//(data[i]/div)*div
        }
    
    }
    
    void colorReduce2(Mat &image, int div = 64)//time=2.06ms
    {
        int n1 = image.rows;
        int nc = image.cols*image.channels();
        if (image.isContinuous())//***
        {
            nc = n1*nc;
            n1 = 1;
    
        }
        for (int j = 0; j < n1; j++)
        {
            uchar* data = image.ptr<uchar>(j);
    
            for (int i = 0; i < nc; i++)
                data[i] = data[i] / div*div + div / 2;//(data[i]/div)*div
        }
    
    }
    
    
    void colorReduce3_iterator(Mat &image, int div = 64)//time=58.15ms
    {
    
        Mat_<Vec3b>::iterator it = image.begin<Vec3b>();
        Mat_<Vec3b>::iterator itend = image.end<Vec3b>();
        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 colorReduce4(Mat &image, int div = 64) // mermory slip out //time=97.67ms
    {
        int n1 = image.rows;
        int nc = image.cols; //is not nc= image.cols*image.channels();
        
        for (int j = 0; j < n1; j++)
        {
            for (int i = 0; i < nc; i++)
            {
                image.at<Vec3b>(j, i)[0] = image.at<Vec3b>(j, i)[0] / div*div + div / 2;
                image.at<Vec3b>(j, i)[1] = image.at<Vec3b>(j, i)[1] / div*div + div / 2;
                image.at<Vec3b>(j, i)[2] = image.at<Vec3b>(j, i)[2] / div*div + div / 2;
            }
        }
    }
    
    void colorReduce5_fast(Mat &image, int div = 64)//time=1.13ms
    {
        int n1 = image.rows;
        int nc = image.cols;    
        if (image.isContinuous())//***
        {
            nc = n1*nc;
            n1 = 1;
        }
        int n = static_cast<int>(log(static_cast<double>(div))/log(2.0));
    
        uchar mask = 0xff << n;
    
        for (int j = 0; j < n1; j++)
        {
            uchar* data = image.ptr<uchar>(j);
    
            for (int i = 0; i < nc; i++)
            {
                *data++ = *data&mask + div / 2;
                *data++ = *data&mask + div / 2;
                *data++ = *data&mask + div / 2;
            }
        }
    }
    
    
    
    void main()
    {    
        Mat image = imread("lena.jpg");
    
        //Time test
        double tTime;
        tTime = (double)getTickCount();
        const int nTimes = 100;
        for (int i = 0; i < nTimes; i++)
        {
            //algrithom to be test ;
            colorReduce4(image);
        }
        tTime = 1000 * ((double)getTickCount() - tTime) /
            getTickFrequency();
        tTime /= nTimes;
        std::cout << tTime << std::endl;
    
        namedWindow("Image");
        imshow("Image", image);
    
        waitKey(0);
    
    }

    main()函数中,增加了Time test 函数,为了测试不同的图像遍历方法的运行效率。经过测试,每个遍历方法的运行时间,我已经注释在每一个colorReduce函数的后面。

    从以上的结果来看,效率最高最低的排序是:colorReduce5_fast()>colorReduce2()>colorReduce1()>colorReduce3_iterator()>colorReduce4();

    效率最高只需要占用1.13ms,效率最低要占用97.67ms。效率相差100倍左右,性能将提升90%以上;

    从代码易读性上来排序(个人主观):

    colorReduce3_iterator()>colorReduce4()>colorReduce1()>colorReduce2()>colorReduce5_fast();

    综合考虑算法处理效率与代码易读性,我通常选择:

    colorReduce1()>colorReduce2();

    分析,不同的图像遍历方法:

    colorReduce5_fast()

     遍历方法:使用指针,减少嵌套循环

    >colorReduce2()

     遍历方法:使用指针,减少嵌套循环

    >colorReduce1()

    遍历方法:使用指针

    >colorReduce3_iterator()

     遍历方法:使用迭代器

    >colorReduce4()

     遍历方法:使用迭代器at()

    从上面的不同的遍历方法来看,得出结论:为了提高遍历效率,尽量使用指针,而不是迭代器;尽量减少嵌套循环;

  • 相关阅读:
    lua table
    lua basic
    lua5.4 coroutine的通俗理解
    HarmonyOS实战—实现双击事件
    HarmonyOS实战—单击事件的四种写法
    HarmonyOS实战—实现单击事件流程
    苹果CMS对接公众号教程
    Spring快速入门
    YYCMS搭建影视网站教程
    分享几个开源Java写的博客系统
  • 原文地址:https://www.cnblogs.com/pans0ul/p/9639193.html
Copyright © 2011-2022 走看看