原文:https://www.cnblogs.com/Anita9002/p/7097575.html
参考:http://blog.csdn.net/trent1985/article/details/50904173
根据国外一篇大牛的文章:No-Reference Perceptual Quality Assessment of JPEG Compressed Images
在无参考图像的质量评价中,图像的清晰度是衡量图像质量优劣的重要指标,它能够较好的与人的主观感受相对应,图像的清晰度不高表现出图像的模糊。本文针对无参考图像质量评价应用,对目前几种较为常用的、具有代表性清晰度算法进行讨论分析,为实际应用中选择清晰度算法提供依据。
对于JPEG图像,根据大牛的文章,写成的MATLAB代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
|
调用的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\n',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\n',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 << "\n";
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;
}