美文网首页
像素遍历

像素遍历

作者: 看风景的人_21744 | 来源:发表于2017-10-18 23:28 被阅读0次

    当处理图片的像素值时,如变化i=(i/10)*10。没有必要对每一个像素值进行这个操作。可以创建一个表,如果是灰度图像,那么表达大小是256*常数2。之后对每一个像素进行查表即可。

    运行时间的计算:

    double t = (double)getTickCount();
    // do something ...
    t = ((double)getTickCount() - t)/getTickFrequency();
    

    在内存中,图像每行的像素存储一般是是连续的。

    C的遍历

    Mat& ScanImageAndReduceC(Mat& I, const uchar* const table)
    {
        // accept only char type matrices
        CV_Assert(I.depth() == CV_8U);
        int channels = I.channels();
        int nRows = I.rows;
        int nCols = I.cols * channels;
        if (I.isContinuous())
        {
            nCols *= nRows;
            nRows = 1;
        }
        int i,j;
        uchar* p;
        for( i = 0; i < nRows; ++i)
        {
            p = I.ptr<uchar>(i);
            for ( j = 0; j < nCols; ++j)
            {
                p[j] = table[p[j]];
            }
        }
        return I;
    }
    

    迭代器方法

    Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table)
    {
        // accept only char type matrices
        CV_Assert(I.depth() == CV_8U);
        const int channels = I.channels();
        switch(channels)
        {
        case 1:
            {
                MatIterator_<uchar> it, end;
                for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it)
                    *it = table[*it];
                break;
            }
        case 3:
            {
                MatIterator_<Vec3b> it, end;
                for( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end; ++it)
                {
                    (*it)[0] = table[(*it)[0]];
                    (*it)[1] = table[(*it)[1]];
                    (*it)[2] = table[(*it)[2]];
                }
            }
        }
        return I;
    }
    

    typedef Vec<uchar, 3> cv::Vec3b
    typedef Vec<double, 3> cv::Vec3d
    typedef Vec<float, 3> cv::Vec3f
    typedef Vec<int, 3> cv::Vec3i
    typedef Vec<short, 3> cv::Vec3s
    typedef Vec<ushort, 3> cv::Vec3w

    On-the-fly address calculation with reference returning

    Mat& ScanImageAndReduceRandomAccess(Mat& I, const uchar* const table)
    {
        // accept only char type matrices
        CV_Assert(I.depth() == CV_8U);
        const int channels = I.channels();
        switch(channels)
        {
        case 1:
            {
                for( int i = 0; i < I.rows; ++i)
                    for( int j = 0; j < I.cols; ++j )
                        I.at<uchar>(i,j) = table[I.at<uchar>(i,j)];
                break;
            }
        case 3:
            {
             Mat_<Vec3b> _I = I;
             for( int i = 0; i < I.rows; ++i)
                for( int j = 0; j < I.cols; ++j )
                   {
                       _I(i,j)[0] = table[_I(i,j)[0]];
                       _I(i,j)[1] = table[_I(i,j)[1]];
                       _I(i,j)[2] = table[_I(i,j)[2]];
                }
             I = _I;
             break;
            }
        }
        return I;
    }
    

    很慢,不过要处理少数个数据时候,可以参考。Mat_data type神器呀!

    最好的方法

    Mat lookUpTable(1, 256, CV_8U);
        uchar* p = lookUpTable.ptr();
        for( int i = 0; i < 256; ++i)
            p[i] = table[i];
    
    LUT(I, lookUpTable, J);
    

    速度最快,因为This is because the OpenCV library is multi-thread enabled via Intel Threaded Building Blocks.
    不过牺牲了一些安全性。

    相关文章

      网友评论

          本文标题:像素遍历

          本文链接:https://www.haomeiwen.com/subject/horyuxtx.html