opencv3_note2:使用三種方式遍歷像素

1.什麼是一幅圖像———(摘自《數字圖像處理疑難解析》)

1.就單色圖像而言,是一個二維的光強函數f(x,y),其中的x和y是空間座標,f(x,y)正比於圖像在該點的亮度值;若是一幅彩色圖,則f

是一個向量,每一個分量代表着一個顏色分量

2.數字圖像在空間座標和亮度值都離散化的圖像f(x,y)中,它可以用一個或者若干個數組來表示數組的每一個元素稱爲像素(pixel)

2.顏色空間縮減算法

2-1:有的時候 單通道圖的像素值可以有0-255種,但是,如果三通道的圖可以有255^3種類別,在適當的時候,對像素值進行省略可以簡化計算量

2-2:算法公式

a=(a/div+div)+div/2; 定義合適的div

2-3:算法邏輯實現:

遍歷圖像矩陣的每一個像素,然後對像素應用上述公式

2-4:

其實算法的實現並不難,但是,實現像素的遍歷值得一提,下面採用三種方式實現遍歷像素的效果

#include<opencv2/opencv.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
#define PICTURE_ADRESS "C:\\Users\\ASUS\\Pictures\\opencv_Pirture\\2.jpg"

    void colorReduce(cv::Mat &input_picture, cv::Mat &output_picture, int div);
    int main()
    {
        cv::Mat dstImage;
        cv::Mat srcImage = cv::imread(PICTURE_ADRESS);
        if (!srcImage.data)
        {
            std::cout << "read it error" << std::endl;
            return false;
        }
        dstImage.create(srcImage.rows, srcImage.cols, srcImage.type());//初始化dstImage
        colorReduce(srcImage, dstImage, 32);
        cv::imshow("origin_picture", srcImage);
        cv::imshow("result_picture", dstImage);
        
        while (!(char(cv::waitKey(10)) == 's'));//按鍵退出
        return 0;
        system("pause");
    }


//solution 1:使用指針 方法運行效率高,但是比較難以理解
    /*void colorReduce(cv::Mat& input_picture, cv::Mat& output_picture, int div)
    {
        output_picture = input_picture.clone();//創建副本
        int row_num = output_picture.rows;
        int col_num = output_picture.cols*output_picture.channels();//將類和通道數歸一處理
        for (int i = 0; i < row_num; i++)
        {
            uchar *data = output_picture.ptr<uchar>(i);//獲取第i行的首地址
            for (int j = 0; j < col_num; j++)
            {
                data[j] = data[j] / div*div + div / 2;//核心算法
            }
        }
    }*/
//solution2 :使用迭代器進行像素的訪問 需要會使用一些向量
    /*void colorReduce(cv::Mat& input_picture, cv::Mat& output_picture, int div)
    {
        output_picture = input_picture.clone();
        //定義迭代器
        cv::Mat_<cv::Vec3b>::iterator it = output_picture.begin<cv::Vec3b>();
        cv::Mat_<cv::Vec3b>::iterator itend = output_picture.end<cv::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;
        }
    }*/
//solution3 :使用動態地址計算 .at方法 簡單易懂 但是運行效率沒有前兩種高(個人推薦)
    void colorReduce(cv::Mat& input_picture, cv::Mat& output_picture, int div)
    {
        output_picture = input_picture.clone();    
        int col_num = output_picture.cols;
        int row_num = output_picture.rows;
        for (int i = 0; i < row_num; i++)
        {
            for (int j = 0; j < col_num; j++)
            {
                output_picture.at<cv::Vec3b>(i, j)[0] = output_picture.at<cv::Vec3b>(i, j)[0] / div*div + div / 2;
                output_picture.at<cv::Vec3b>(i, j)[1] = output_picture.at<cv::Vec3b>(i, j)[1] / div*div + div / 2;
                output_picture.at<cv::Vec3b>(i, j)[2] = output_picture.at<cv::Vec3b>(i, j)[2 ] / div*div + div / 2;

            }
        }

        //其實三種方法都是用不同的方式提取出了圖像中的像素點 然後加以處理
        //pixel=pxel/div*div+div/2;
    }

2-5:效果圖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章