//
// Created by sy on 19-5-15.
//
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
#include <sys/types.h>
#include <dirent.h>
/** 常用的清晰度评价算法有:
" 频域函数 :对焦越好、高频部分越多,细节越多,图像越清晰.
" 灰度函数 :对焦越好,和周围相邻灰度点差值越大,边缘越清晰,图像越清晰。
" 信息熵函数:对焦越好,图像包含的信息熵越大,包含信息量更大,图像越清晰。
" 统计学函数:对焦越好,直方图多样性越好,图像越清晰。
*/
double pixAssement(cv::Mat src, double &time){
cv::Mat gray,sobel,mean,image_x,image_y;
cv::cvtColor(src,gray,CV_RGB2GRAY);
double start,end;
start=cv::getTickCount();
// Tenengrad 梯度
cv::Sobel(gray,sobel,CV_16U,1,1); //2ms
// 拉普拉斯算子;
// cv::Laplacian(gray,sobel,CV_16U); //3ms
// Brenner 相邻灰度差的平方
// cv::meanStdDev(src,mean,sobel); //0.15ms
// cv::Mat kernel_x(3,3,CV_32F,cv::Scalar(0));
// kernel_x.at<float>(1,2)=-1.0;
// kernel_x.at<float>(1,1)=1.0;
// cv::Mat kernel_y(3,3,CV_32F,cv::Scalar(0));
// kernel_y.at<float>(0,1)=-1.0;
// kernel_y.at<float>(1,1)=1.0;
//
// cv::filter2D(gray,image_x,gray.depth(),kernel_x);
// cv::filter2D(gray,image_y,gray.depth(),kernel_y);
// SMD 灰度方差 1.2ms
// image_x=cv::abs(image_x);
// image_y=cv::abs(image_y);
// sobel=image_x+image_y;
// SMD2 灰度方差乘积 1.2ms
// image_x=cv::abs(image_x);
// image_y=cv::abs(image_y);
// cv::multiply(image_x,image_y,sobel);
// 能量梯度函数 1.25ms
// cv::multiply(image_x,image_x,image_x);
// cv::multiply(image_y,image_y,image_y);
// sobel=image_x+image_y;
end=cv::getTickCount();
std::cout << "the exe time filter : " << (end - start) / (cv::getTickFrequency())<<" s"<< std::endl;
time=end-start;
double meanValue=cv::mean(sobel)[0];
return meanValue;
}
// 峰值信噪比 返回一个float30~50 越大相符程度越高
double PSNR(cv::Mat &ref,cv::Mat& src){ //2~3ms
double psnr= cv::PSNR(ref, src);
return psnr;
}
// 信噪比
double SNR(cv::Mat &src){
}
// 结构相似性 返回一个0~1之间的浮点数,越大越高,该算法对每一个通道有值
cv::Scalar SSIM( cv::Mat & ref, cv::Mat& src){
const double C1=6.5025,C2=58.5225;
cv::Mat average1,average2,sigma1_2,sigma2_2,sigma12,t1,t2,t3;
ref.convertTo(ref,CV_32F);
src.convertTo(src,CV_32F);
cv::Mat I1_2=ref.mul(ref);
cv::Mat I2_2=src.mul(src);
cv::Mat I1_I2=ref.mul(src);
cv::GaussianBlur(ref,average1,cv::Size(11,11),1.5);
cv::GaussianBlur(src,average2,cv::Size(11,11),1.5);
cv::Mat average1_2=average1.mul(average1);
cv::Mat average2_2=average2.mul(average2);
cv::Mat average12=average1.mul(average2);
cv::GaussianBlur(I1_2,sigma1_2,cv::Size(11,11),1.5);
sigma1_2-=average1_2;
cv::GaussianBlur(I2_2,sigma2_2,cv::Size(11,11),1.5);
sigma2_2-=average2_2;
cv::GaussianBlur(I1_I2,sigma12,cv::Size(11,11),1.5);
sigma12-=average12;
t1=2*average12+C1;
t2=2*sigma12+C2;
t3=t1.mul(t2);
t1=average1_2+average2_2+C1;
t2=sigma1_2+sigma2_2+C2;
t1=t1.mul(t2);
cv::Mat SSIM;
cv::divide(t3,t1,SSIM);
cv::Scalar mssim=cv::mean(SSIM);
return mssim;
}
int main(){
cv::Mat draw=cv::Mat::zeros(cv::Size(840,680),CV_8UC3);
for (int i = 0; i < draw.cols * draw.rows * draw.channels(); ++i) {
draw.data[i]=255;
}
// cv::imshow("draw",draw);
// cv::waitKey();
std::string filedir="/home/sy/data/work/assement/clearness/123/";
const char *fileDir=filedir.c_str();
int num=0; // 文件个数;
std::vector<float>value;
float maxValue=0;
double time_total=0;
DIR * dir;
dir =opendir(fileDir);
struct dirent*ptr;
while (ptr=readdir(dir)){
if(ptr->d_name[0]=='.'){
continue;
}
// char * fileDir=(char*)malloc(strlen(filedir)+strlen(ptr->d_name)+1);
// for (int i = 0; filedir[i] !='\0' ; ++i) {
// fileDir[i]=filedir[i];
// }
// for (int j = 0; ptr->d_name[j]!='\0' ; ++j) {
// fileDir[j+strlen(filedir)]=ptr->d_name[j];
// }
// fileDir[strlen(filedir)+strlen(ptr->d_name)]='\0';
// cv::Mat src=cv::imread(fileDir);
// double value_=pixAssement(src);
// value[num]=value_;
num++;
}
for (int i = 0; i < num-1; ++i) {
std::string filename=filedir+"image"+std::to_string(i+1)+".jpg";
cv::Mat src=cv::imread(filename);
double time=0;
double value_p=pixAssement(src,time);
time_total=time_total+time;
value.push_back(value_p);
if(value_p>maxValue){
maxValue=value_p;
}
}
float col_step=draw.cols/(num+1);
float row_step=draw.rows/(maxValue+1);
for (int k = 0; k <num-1 ; ++k) {
std::cout<<value[k]<<std::endl;
cv::Point p1(k*col_step,draw.rows-value[k]*row_step);
cv::Point p2((k+1)*col_step,draw.rows-value[k+1]*row_step);
cv::line(draw,p1,p2,cv::Scalar(255,0,0),1);
cv::putText(draw,std::to_string(value[k]),p1,CV_FONT_HERSHEY_COMPLEX,0.3,cv::Scalar(0,0,255),1);
}
std::cout<<"total time:"<<time_total<<std::endl;
std::stringstream meanValueStream;
std::string meanValueString;
meanValueStream >>meanValueString;
// energy gradient
meanValueString=" Tenengrad: average time-"+std::to_string(time_total/(num*cv::getTickFrequency()))+"s";
cv::putText(draw,meanValueString,cv::Point(20,620),CV_FONT_HERSHEY_COMPLEX,0.6,cv::Scalar(255,0,255),2);
std::string drawName=filedir+"assement/Tenengrad.jpg";
cv::imwrite(drawName,draw);
cv::imshow("draw",draw);
cv::waitKey();
}
the best algorithm from
cv::Mat kernel, src_32f, dst;
float data[8][8] = {
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, 3, 3, 3, 3, -1, -1},
{-1, -1, 3, 3, 3, 3, -1, -1},
{-1, -1, 3, 3, 3, 3, -1, -1},
{-1, -1, 3, 3, 3, 3, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1}
};
kernel = cv::Mat(8, 8, CV_32F, data);
gray.convertTo(src_32f, CV_32F);
cv::filter2D(src_32f, dst, -1, kernel);
double power = 0, score = 0;
const int FOCUS_SCORE_50PERCENT = 60;
for (int row = 0; row < dst.rows; ++row) {
for (int col = 0; col < dst.cols; ++col) {
power += abs(dst.at<float>(row, col));
}
}
power = power / (dst.cols * dst.rows);
score = ((power * power) / (power * power + FOCUS_SCORE_50PERCENT * FOCUS_SCORE_50PERCENT) * 100.0f + 0.5f);