基於邊緣寬度的圖像清晰度檢測

論文:《基於強邊緣寬度直方圖的圖像清晰度指標.pdf》


實現:

#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
#define mydebug
#define test
using namespace cv;
namespace ImageUtil {


float getImageQuality_patchbased(cv::Mat& m,int patchsize,int overlap){

}


    float getImageQuality(cv::Mat& m)
    {
        int nr=m.rows;
        int nc=m.cols;
        Mat g_x(nr,nc,CV_32FC1);//垂直邊緣圖
        Mat g_y(nr,nc,CV_32FC1);//水平邊緣圖
        float thresh_x=0.0f;
        float thresh_y=0.0f;
#ifdef test
        float metric=0.0;
#endif
        for(int i=1;i!=nr-1;i++)
        {
            const uchar* up_line=m.ptr<uchar>(i-1);
            const uchar* mid_line=m.ptr<uchar>(i);
            const uchar* down_line=m.ptr<uchar>(i+1);
            float* cur_x_line=g_x.ptr<float>(i);
            float* cur_y_line=g_y.ptr<float>(i);
            for(int j=1;j!=nc-1;j++)
            {
                cur_x_line[j]=(up_line[j-1]-up_line[j+1])+
                        (mid_line[j-1]-mid_line[j+1])*2+
                        (down_line[j-1]-down_line[j+1]);
                cur_y_line[j]=(up_line[j-1]-down_line[j-1])+
                        (up_line[j]-down_line[j])*2+
                        (up_line[j+1]-down_line[j+1]);
                thresh_x+=cur_x_line[j]*cur_x_line[j];
                thresh_y+=cur_y_line[j]*cur_y_line[j];
#ifdef test
                metric+=std::abs(cur_x_line[j]*cur_x_line[j])+std::abs(cur_y_line[j]*cur_y_line[j]);
#endif
            }
        }

        g_x.row(0).setTo(cv::Scalar(0.0f));
        g_x.row(nr-1).setTo(cv::Scalar(0.0f));
        g_x.col(0).setTo(cv::Scalar(0.0f));
        g_x.col(nc-1).setTo(cv::Scalar(0.0f));
        g_y.row(0).setTo(cv::Scalar(0.0f));
        g_y.row(nr-1).setTo(cv::Scalar(0.0f));
        g_y.col(0).setTo(cv::Scalar(0.0f));
        g_y.col(nc-1).setTo(cv::Scalar(0.0f));

        thresh_x=4*thresh_x/nr/nc;
        thresh_y=4*thresh_y/nr/nc;
#ifdef mydebug
        //std::cout<<"g_x:"<<std::endl<<g_x<<std::endl;
        //std::cout<<"g_y:"<<std::endl<<g_y<<std::endl;
        Mat temp_x,temp_y;
        g_x.convertTo(temp_x,CV_8UC1);
        g_y.convertTo(temp_y,CV_8UC1);
        cv::imshow("水平梯度圖",temp_x);
        cv::imshow("垂直直方圖",temp_y);
        Mat b_x=Mat::zeros(nr,nc,CV_8UC1);
        Mat b_y=Mat::zeros(nr,nc,CV_8UC1);

#endif
#ifdef test
        std::cout<<"test metricd:"<<metric/nr/nc<<std::endl;
        return metric/nr/nc;
#endif
        int e_hist_x[nr];//水平邊緣寬度直方圖
        int e_hist_y[nc];//垂直邊緣寬度直方圖
        for(int i=0;i<nr;i++)   e_hist_x[i]=0.0f;
        for(int i=0;i<nc;i++)   e_hist_y[i]=0.0f;
        int nw_x=0;
        int nw_y=0;
        for(int i=1;i!=nr-1;i++){
            float* cur_x_line=g_x.ptr<float>(i);
            float* cur_y_line=g_y.ptr<float>(i);
            for(int j=1;j!=nc-1;j++){
                if(cur_x_line[j]*cur_x_line[j]>thresh_x){//計算垂直方向邊緣寬度
#ifdef mydebug
                    b_x.ptr<uchar>(i)[j]=255;
#endif
                    float up=g_x.ptr<float>(i-1)[j];
                    float down=g_x.ptr<float>(i+1)[j];
                    float cur=g_x.ptr<float>(i)[j];
                    int w_x_u=1;
                    int w_x_d=1;
                    if(up>=cur && cur>=down){//如果是遞減邊緣
                        float t_up=up;
                        float t_cur_up=cur;
                        while(t_up>t_cur_up && i>w_x_u)
                        {
                            w_x_u++;
                            t_cur_up=t_up;
                            t_up=g_x.ptr<float>(i-w_x_u)[j];
                        }
                        w_x_u--;
                        float t_down=down;
                        float t_cur_down=cur;
                        while(t_down<t_cur_down && i<nr-w_x_d){
                            w_x_d++;
                            t_cur_down=t_down;
                            t_down=g_x.ptr<float>(i+w_x_d)[j];
                        }
                        w_x_d--;

                    }
                    else if(up<=cur && cur<=down){//如果是遞增邊緣
                        float t_up=up;
                        float t_cur_up=cur;
                        while(t_up<t_cur_up && i>w_x_u){
                            w_x_u++;
                            t_cur_up=t_up;
                            t_up=g_x.ptr<float>(i-w_x_u)[j];
                        }
                        w_x_u--;
                        float t_down=down;
                        float t_cur_down=cur;
                        while(t_down>t_cur_down && i<nr-w_x_d){
                            w_x_d++;
                            t_cur_down=t_down;
                            t_down=g_x.ptr<float>(i+w_x_d)[j];
                        }
                        w_x_d--;
                    }
                    e_hist_x[w_x_d+w_x_u]++;
                    nw_x++;
                }
                if(cur_y_line[j]*cur_y_line[j]>thresh_y){//計算水平方向邊緣寬度
#ifdef mydebug
                    b_y.ptr<uchar>(i)[j]=255;
#endif
                    float left=cur_y_line[j-1];
                    float right=cur_y_line[j+1];
                    float cur=cur_y_line[j];
                    int w_y_l=1;
                    int w_y_r=1;
                    if(left>=cur && cur>=right){//如果是遞減邊緣
                        float t_left=left;
                        float t_cur_left=cur;
                        while(t_left>t_cur_left && j>w_y_l)
                        {
                            w_y_l++;
                            t_cur_left=t_left;
                            t_left=cur_y_line[j-w_y_l];
                        }
                        w_y_l--;
                        float t_right=right;
                        float t_cur_right=cur;
                        while(t_right<t_cur_right && j<nc-w_y_r){
                            w_y_r++;
                            t_cur_right=t_right;
                            t_right=cur_y_line[j+w_y_r];
                        }
                        w_y_r--;

                    }
                    else if(left<=cur && cur<=right){//如果是遞增邊緣
                        float t_left=left;
                        float t_cur_left=cur;
                        while(t_left<t_cur_left && j>w_y_l){
                            w_y_l++;
                            t_cur_left=t_left;
                            t_left=cur_y_line[j-w_y_l];
                        }
                        w_y_l--;
                        float t_right=right;
                        float t_cur_right=cur;
                        while(t_right>t_cur_right && j<nc-w_y_r){
                            w_y_r++;
                            t_cur_right=t_right;
                            t_right=cur_y_line[j+w_y_r];
                        }
                        w_y_r--;
                    }
                    e_hist_y[w_y_l+w_y_r]++;
                    nw_y++;
                }
            }
        }

#ifdef mydebug
        //std::cout<<"b_x"<<std::endl<<b_x<<std::endl;
        //std::cout<<"b_y"<<std::endl<<b_y<<std::endl;
        imshow("b_x",b_x);
        imshow("b_y",b_y);
        std::cout<<"e_hist_x:";
        for(int i=0;i<nr;i++)
        {
            std::cout<<e_hist_x[i]<<",";
        }
        std::cout<<std::endl;
        std::cout<<"e_hist_y:";
        for(int i=0;i<nc;i++){
            std::cout<<e_hist_y[i]<<",";
        }
        std::cout<<std::endl;
#endif
        //計算x方向清晰度評價值
        int wm_x=0,we_x=0;
        float maxEdge_x=0.0f;
        for(int i=0;i<nr;i++){
            if(e_hist_x[i]>maxEdge_x){
                maxEdge_x=e_hist_x[i];
                wm_x=i;
            }
            if(e_hist_x[i]!=0)  we_x=i;
        }
        float metric_x=0.0f;
        for(int i=0;i!=we_x;i++){
            float d=1.0f;
            if(i<wm_x) d=(i*i*1.0f)/(wm_x*wm_x);
            else if(i==wm_x)    d=1;
            else d=((we_x-i)*(we_x-i)*1.0f)/((we_x-wm_x)*(we_x-wm_x));
            float p=e_hist_x[i]*1.0f/nw_x;
            metric_x+=d*p*(i);
        }
#ifdef mydebug

#endif
        //計算y方向清晰度評價值
        int wm_y=0,we_y=0;
        float mayEdge_y=0.0f;
        for(int i=0;i<nc;i++){
            if(e_hist_y[i]>mayEdge_y){
                mayEdge_y=e_hist_y[i];
                wm_y=i;
            }
            if(e_hist_y[i]!=0)  we_y=i;
        }
        float metric_y=0.0f;
        for(int i=0;i!=we_y;i++){
            float d=1.0f;
            if(i<wm_y) d=(i*i*1.0f)/(wm_y*wm_y);
            else if(i==wm_y)    d=1;
            else d=((we_y-i)*(we_y-i)*1.0f)/((we_y-wm_y)*(we_y-wm_y));
            float p=e_hist_y[i]*1.0f/nw_y;
            metric_y+=d*p*(i);
        }
#ifdef mydebug
        std::cout<<"metric_x:"<<metric_x<<std::endl;
        std::cout<<"metric_y:"<<metric_y<<std::endl;
        std::cout<<"metric:"<<(metric_x+metric_y)/2<<std::endl;
#endif
        return (metric_x+metric_y)/2;
    }

}


發佈了74 篇原創文章 · 獲贊 58 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章