zoukankan      html  css  js  c++  java
  • opencv---JPEG图像质量检测代码

    参考:http://blog.csdn.net/trent1985/article/details/50904173

    根据国外一篇大牛的文章:No-Reference Perceptual Quality Assessment of JPEG Compressed Images

    在无参考图像的质量评价中,图像的清晰度是衡量图像质量优劣的重要指标,它能够较好的与人的主观感受相对应,图像的清晰度不高表现出图像的模糊。本文针对无参考图像质量评价应用,对目前几种较为常用的、具有代表性清晰度算法进行讨论分析,为实际应用中选择清晰度算法提供依据。

    对于JPEG图像,根据大牛的文章,写成的MATLAB代码如下:

    function score = jpeg_quality_score(img)
    
    %========================================================================
    %
    %Copyright (c) 2002 The University of Texas at Austin
    %All Rights Reserved.
    % 
    %This program is free software; you can redistribute it and/or modify
    %it under the terms of the GNU General Public License as published by
    %the Free Software Foundation; either version 2 of the License, or
    %(at your option) any later version.
    % 
    %This program is distributed in the hope that it will be useful,
    %but WITHOUT ANY WARRANTY; without even the implied warranty of
    %MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    %GNU General Public License for more details.
    % 
    %The GNU Public License is available in the file LICENSE, or you
    %can write to the Free Software Foundation, Inc., 59 Temple Place -
    %Suite 330, Boston, MA 02111-1307, USA, or you can find it on the
    %World Wide Web at http://www.fsf.org.
    %
    %Author  : Zhou Wang 
    %Version : 1.0
    % 
    %The authors are with the Laboratory for Image and Video Engineering
    %(LIVE), Department of Electrical and Computer Engineering, The
    %University of Texas at Austin, Austin, TX.
    %
    %Kindly report any suggestions or corrections to zhouwang@ieee.org
    %
    %========================================================================
    %
    %This is an implementation of the algorithm for calculating the quality
    %score of JPEG compressed images proposed by Zhou Wang, Hamid R. Sheikh
    %and Alan C. Bovik. Please refer to the paper: Zhou Wang, Hamid R. Sheikh
    %and Alan C. Bovik, "No-Reference Perceptual Quality Assessment of JPEG
    %Compressed Images," submitted to IEEE International Conference on Image
    %Processing, Sept. 2002.
    %
    %You can change this program as you like and use it anywhere, but please
    %refer to its original source (cite our paper and our web page at
    %http://anchovy.ece.utexas.edu/~zwang/research/nr_jpeg_quality/index.html).
    %
    %Input : A test 8bits/pixel grayscale image loaded in a 2-D array
    %Output: A quality score of the image. The score typically has a value
    %        between 1 and 10 (10 represents the best quality, 1 the worst).
    %
    %Usage:
    %
    %1. Load the image, for example
    %
    %   image = imread('testimage.jpg'); 
    %
    %2. Call this function to calculate the quality score:
    %
    %   Quality_Score = jpeg_quality_score(image)
    %
    %========================================================================
    % img=imread('/Users/anitafang/Desktop/testimg/test0.jpg');
    
    if (nargin > 1)
        score = -1;
        return;
    end
    
    %  [M,N] = size(img);
    %  if (M < 16 | N < 16)
    %      score = -2;
    %      return;
    %  end
     
    x1= rgb2gray(img);
    x = double(x1);
    [M,N] = size(x);
    
    % Feature Extraction:
    
    % 1. horizontal features
    
    d_h = x(:, 2:N) - x(:, 1:(N-1));
    % [m, n]=size(d_h);
    %  disp(d_h);
    %  fprintf('img width %d,and height %d,length %d, dims %d
    ',M,N,length(img),ndims(img));
    %  fprintf('d_h width %d,and height %d, length %d, dims %d
    ',m,n,length(d_h),ndims(d_h));
    
    
    
    B_h = mean2(abs(d_h(:, 8:8:8*(floor(N/8)-1))));
    
    A_h = (8*mean2(abs(d_h)) - B_h)/7;
    
    sig_h = sign(d_h);
    left_sig = sig_h(:, 1:(N-2));
    right_sig = sig_h(:, 2:(N-1));
    Z_h = mean2((left_sig.*right_sig)<0);
    
    %  fprintf('B_h:%f,A_h:%f,Z_h:%f,
    ',B_h,A_h,Z_h);
    
    % 2. vertical features
    
    d_v = x(2:M, :) - x(1:(M-1), :);
    
    B_v = mean2(abs(d_v(8:8:8*(floor(M/8)-1), :)));
    
    A_v = (8*mean2(abs(d_v)) - B_v)/7;
    
    sig_v = sign(d_v);
    up_sig = sig_v(1:(M-2), :);
    down_sig = sig_v(2:(M-1), :);
    Z_v = mean2((up_sig.*down_sig)<0);
    
    % 3. combined features
    
    B = (B_h + B_v)/2;
    A = (A_h + A_v)/2;
    Z = (Z_h + Z_v)/2;
    
    % Quality Prediction
    
    alpha = -245.8909;
    beta = 261.9373;
    gamma1 = -239.8886;
    gamma2 = 160.1664;
    gamma3 = 64.2859;
    
    score = alpha + beta*(B.^(gamma1/10000))*(A.^(gamma2/10000))*(Z.^(gamma3/10000));
    

     调用的main函数:

    function main()
    
    allNum = 0;
    blurNum = 0;
    
    threshold = 7.7;
    
    
    for  k = 0:2000
        try
            image = imread(['/Users/anitafang/Desktop/testimg/','test',num2str(k),'.jpg']);
            %image = imread(['/Users/user/Desktop/test/ye_blur/',num2str(k),'.jpg']);
            quality_score = jpeg_quality_score(image);
            fprintf('Quality_Score:%d.jpg  %f
    ',k,quality_score);
            allNum = allNum + 1;
            
            if quality_score < threshold
               blurNum = blurNum + 1;
               savePath = ['/Users/anitafang/Desktop/blur/',num2str(k),'.jpg'];
               imwrite(image,savePath);
            end
    %         break
        catch err
            %throw(err);
        end
    end
    
    % fprintf('relevance:%f
    ',blurNum/allNum)

    为了集成方便,把它变成c++代码,调研opencv库:

    //
    //  jpegquality.hpp
    //  SDM_Train
    //
    //  Created by anitafang on 2017/6/27.
    //  Copyright © Anita,fang. All rights reserved.
    //
    
    #ifndef jpegquality_hpp
    #define jpegquality_hpp
    
    #include <stdio.h>
    #include <vector>
    #include <iostream>
    #include <time.h>
    #include <fstream>
    #include <math.h> 
    #include <cmath>
    
    #include "opencv2/opencv.hpp"
    #include "opencv2/core/core.hpp"
    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/objdetect/objdetect.hpp"
    
    #endif /* jpegquality_hpp */
    
    using namespace std;
    using namespace cv;
    
    class JPEGQ{
    public:
        JPEGQ();
        void h_feature(Mat x,int M,int N);
        void v_feature(Mat x,int M,int N);
        void combine_feature();
        double qual_predict();
        
    private:
        
        double B_h,A_h,Z_h;
        double B_v,A_v,Z_v;
        double B,A,Z;
    };

    cpp代码是:

    //
    //  jpegquality.cpp
    //  SDM_Train
    //
    //  Created by anitafang on 2017/6/27.
    //  Copyright © 2017年 antia.fang  All rights reserved.
    //
    
    #include "jpegquality.hpp"
    
    
    using namespace std;
    using namespace cv;
    
    
    JPEGQ::JPEGQ(){
        B_h = 0;
        A_h = 0;
        Z_h = 0;
        B_v = 0;
        A_v = 0;
        Z_v = 0;
        B = 0;
        A = 0;
        Z = 0;
    }
      //% 1. horizontal features
    void JPEGQ::h_feature(Mat x,int M,int N){
       
        Mat d_h(M,N-1,CV_64F, Scalar(0,0,255));
        
        for(int i=0;i<M;i++){
            for(int j=0;j<N-1;j++){
                d_h.at<double_t>(i,j)=x.at<double_t>(i,j+1)-x.at<double_t>(i,j);
            }
        }
      //  cout << "d_h = " << d_h << "
    ";
        int DEL= floor(N/8);
        Mat d1_h(M,DEL,CV_64F, Scalar(0,0,255));
        
        for (int i=0;i<M;i++){
            for(int j=0;j<DEL;j++){
                d1_h.at<double_t>(i,j)= abs(d_h.at<double_t>(i,8*j+7));
            }
        }
        
        //求矩阵像素的的平均值
        B_h = mean(d1_h)[0];
        A_h = (8*mean(abs(d_h))[0] - B_h)/7;
        
        Mat sig_h(M,N-2,CV_64F, Scalar(0,0,255));
      
        for(int i=0;i<M;i++){
            for(int j=0;j<N-1;j++){
                if(d_h.at<double_t>(i,j) < 0){
                    sig_h.at<double_t>(i,j) = -1;
                }
                else if(d_h.at<double_t>(i,j) > 0){
                    sig_h.at<double_t>(i,j) = 1;
                }
                else {
                    sig_h.at<double_t>(i,j) = 0;
                }
            }
        }
        
        Mat left_sig(M,N-2,CV_64F,Scalar(0,0,255));
        Mat right_sig(M,N-2,CV_64F,Scalar(0,0,255));
        
        for(int i=0;i<M;i++){
            for(int j=0;j<N-2;j++){
                left_sig.at<double_t>(i,j)=sig_h.at<double_t>(i,j);
                right_sig.at<double_t>(i,j)=sig_h.at<double_t>(i,j+1);
            }
        }
        
        
        
        //double Z_h = mean2((left_sig.*right_sig)<0);
        Mat multi_sig(M,N-2,CV_64F, Scalar(0,0,255));
        for(int i=0;i<M;i++){
            for(int j=0;j<N-2;j++){
                double temp1=left_sig.at<double_t>(i,j)* right_sig.at<double_t>(i,j);
                if(temp1<0){
                    multi_sig.at<double_t>(i,j)= 1;
                }
                else {
                    multi_sig.at<double_t>(i,j)= 0;
                }
                
            }
        }
        Z_h =mean(multi_sig)[0];
        
       //  cout <<"B_h:  "<< B_h<<"A_h:  "<< A_h<<"Z_h:  "<< Z_h << endl;
        
    }
    
        
     //   % 2. vertical features
    void JPEGQ::v_feature(Mat x,int M,int N){
        
        Mat d_v(M-1,N,CV_64F, Scalar(0,0,255));
        
        for(int i=0;i<M-1;i++){
            for(int j=0;j<N;j++){
                
                d_v.at<double_t>(i,j)=x.at<double_t>(i+1,j)-x.at<double_t>(i,j);
                
            }
        }
        
        int DELV= floor(M/8);
        Mat d1_v(DELV,N,CV_64F, Scalar(0,0,255));
        
        for (int i=0;i<DELV;i++){
            for(int j=0;j<N;j++){
                
                d1_v.at<double_t>(i,j)= abs(d_v.at<double_t>(8*i+7,j));
            }
        }
        
        //求矩阵像素的的平均值
        
        B_v=mean(d1_v)[0];
        A_v = (8*mean(abs(d_v))[0] - B_v)/7;
        
        
        Mat sig_v(M-1,N,CV_64F, Scalar(0,0,255));
        
        for(int i=0;i<M-1;i++){
            
            for(int j=0;j<N;j++){
                
                if(d_v.at<double_t>(i,j)<0)
                {  sig_v.at<double_t>(i,j)=-1;  }
                
                else if(d_v.at<double_t>(i,j) >0)
                {  sig_v.at<double_t>(i,j) = 1;  }
                
                else {  sig_v.at<double_t>(i,j) = 0;}
                
            }
        }
        
        Mat up_sig(M-2,N,CV_64F, Scalar(0,0,255));
        Mat down_sig(M-2,N,CV_64F, Scalar(0,0,255));
        
        for(int i=0;i<M-2;i++){
            for(int j=0;j<N;j++){
                
                up_sig.at<double_t>(i,j)=sig_v.at<double_t>(i,j);
                down_sig.at<double_t>(i,j)=sig_v.at<double_t>(i+1,j);
                
            }
        }
        
        //double Z_h = mean2((left_sig.*right_sig)<0);
        Mat vmulti_sig(M-2,N,CV_64F, Scalar(0,0,255));
        for(int i=0;i<M-2;i++){
            for(int j=0;j<N;j++){
                double temp2=up_sig.at<double_t>(i,j)* down_sig.at<double_t>(i,j);
                if(temp2<0)
                { vmulti_sig.at<double_t>(i,j)= 1;}
                else { vmulti_sig.at<double_t>(i,j)= 0; }
                
            }
        }
        Z_v =mean(vmulti_sig)[0];
    
        
    }
    
    
    //% 3. combined features
    void JPEGQ::combine_feature(){
        
        B = (B_h + B_v)/2;
        A = (A_h + A_v)/2;
        Z = (Z_h + Z_v)/2;
        
    }
    
    
    //% Quality Prediction
    double JPEGQ::qual_predict(){
        
        double alpha = -245.8909;
        double beta = 261.9373;
        double gamma1 = -239.8886;
        double gamma2 = 160.1664;
        double gamma3 = 64.2859;
        
        double score = alpha + beta*(pow(B,gamma1/10000)*pow(A,gamma2/10000)*pow(Z,gamma3/10000));
        
       
        return score;
    }

    调用的main代码:

    //
    //  main.cpp
    //  jpg_quality
    //
    //  Created by anitafang on 2017/6/28.
    //  Copyright © 2017年 anitafang. All rights reserved.
    //
    #include <iostream>
    #include "jpegquality.hpp"
    
    
    using namespace std;
    using namespace cv;
    
    
    int main(int argc, const char * argv[]) {
        
        char filename[100];
        double threshold = 7.7;
        int num =12;
       // int *pia = new int[num] ();  // 每个元素初始化为0
        
        
        for(int k=0;k<num;k++){
            
            sprintf(filename,"/Users/anitafang/Desktop/VIP/xcode-demo/test-img/testimg/test%d.jpg",k);
        
            Mat x1=imread(filename,IMREAD_GRAYSCALE);
            
            int M=x1.rows;
            int N=x1.cols;
            
            Mat x;
            x1.convertTo(x, CV_64F);//转换成浮点运算
            
            JPEGQ *jpegq = new JPEGQ();
            jpegq->h_feature(x,M, N);
            jpegq->v_feature(x,M, N);
            jpegq->combine_feature();
            double score= jpegq->qual_predict();
            
            if(score<threshold){
                cout<<"this is a blur image"<<endl;
            }
        
            cout<<"the image :"<<k<<" "<<" score is :"<<score<<endl;
            
        }
    
        
        return 0;
    }

    可以看到阈值的设置7.7是个经验值。

  • 相关阅读:
    cordova build android get Execution failed for task ':dexArmv7Debug'
    brew install memcache get Error: Formulae found in multiple taps
    快速激活JetBrains系列产品
    NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
    `libsass` bindings not found. Try reinstalling `node-sass`?
    Cordova 快速入门记录
    perl: warning: Setting locale failed.
    httpclient源码分析之 PoolingHttpClientConnectionManager 获取连接
    httpclient源码分析之MainClientExec
    fastjson从1.1.41升级到1.2.28的坑
  • 原文地址:https://www.cnblogs.com/Anita9002/p/7097575.html
Copyright © 2011-2022 走看看