在抓拍人脸时,为丢掉抓拍质量不高的数据。写了一个程序来测试三种清晰度检测的算法。
程序的主要功能是,依次读取图片文件夹中的图片,进行清晰度检测,每张图片会得到一个清晰度打分结果。为了提高程序执行速度,将清晰度的阈值写在cpg文件里,让程序去读cpg文件里的阈值,与每张图片的打分结果比较,低于此阈值的将放入这个路径的子文件夹(命名为threshold1)中。
并且将每张图片的打分结果,写入txt文件中,可视化打分结果。
》首先需注意的是,为了保证程序在不同阈值下正确运行,需要在每次运行时先清空掉threshold1文件夹,并将其中的图片重新放回遍历到的文件夹中。
这里采用rename方式,将图片路径名改变,使得threshold1文件夹内的图片移出。
》程序主体部分
用FindFirstFileA和FindNextFileA遍历图片文件夹内的文件。
如果图片文件夹中还有子文件夹,则递归操作。
获得图片路径后再加上图片名称,就可以放入计算清晰度的函数中。
这里清晰度检测有三种方法,sobel laplacian,和meanvalue
得到清晰度值后,进入对清晰度值进行判断操作部分。
如果小于阈值,就调用rename函数,将图片移到threshold1文件夹中。
参考:
OpenCV 图像清晰度评价(相机自动对焦) - CSDN博客
#include <highgui/highgui.hpp>
#include <imgproc/imgproc.hpp>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <string>
#include <fstream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <string>
#include <shlwapi.h>
#pragma comment(lib,"shlwapi.lib")
#define INI_FILE _T("cpg.ini")
using namespace cv;
using namespace std;
//int main(int argc, char *argv[])
double calculate(string fileName)
{
string newfileName, grayFile;
stringstream meanValueStream;
string meanValueString;
Mat imageSource = imread(fileName);
Mat imageGrey;
Mat meanValueImage, meanStdValueImage;
cvtColor(imageSource, imageGrey, CV_RGB2GRAY);
Mat imageSobel;
Laplacian(imageGrey, imageSobel, CV_16U, 1, 1);
//Sobel(imageGrey, imageSobel, CV_16U, 1, 1);
//求灰度图像的标准差
/*meanStdDev(imageGrey, meanValueImage, meanStdValueImage);
double meanValue = 0.0;
meanValue = meanStdValueImage.at<double>(0, 0);
*/
//图像的平均灰度
double meanValue = 0.0;
meanValue = mean(imageSobel)[0];
meanValueStream << meanValue;
meanValueStream >> meanValueString;
meanValueString = fileName + ": Articulation(Laplacian):" + meanValueString;
ofstream outfile("路径/ArticulationLaplacianresult.txt", ios::app);
outfile << meanValueString;
outfile << endl;
outfile.close();
return meanValue;
}
//double to string
void opt(string fileName, string imgname, double meanValue)
{
char ThresholdValue[260];
double fThresholdValue;
string newfileName;
WIN32_FIND_DATAA winFindData;
GetPrivateProfileStringA("Threshold", "ThresholdValue", "", ThresholdValue, 260, "D:/AItensor/blurdetector/cpg.ini");
fThresholdValue = atof(ThresholdValue);
string str1 = winFindData.cFileName;
newfileName = "路径/" + imgname;
if (meanValue <= fThresholdValue)
{
rename(fileName.c_str(), newfileName.c_str());
}
}
void judge(const string &strPath)
{
string fileName, filePath;
double meanValue;
string strRawPath = strPath;//传地址
strRawPath.append("\\");//加分隔符
string strFindPath = strRawPath;//在新设一个
strFindPath.append("*.*");//在最外面的目录下查找文件
WIN32_FIND_DATAA winFindData;
HANDLE hTemp = FindFirstFileA(strFindPath.c_str(), &winFindData);//c.str是因为这个函数需要cha类型,返回找到的数据
//if (INVALID_HANDLE_VALUE == hTemp)
// return 0;
while (FindNextFileA(hTemp, &winFindData))
{
string strOldName = winFindData.cFileName;
if ("." == strOldName || ".." == strOldName)
continue;
//如果是目录,则递归继续操作
if (winFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
string strAgain = strPath;
strAgain.append("\\");
strAgain.append(winFindData.cFileName);
judge(strAgain);
continue;
}
//获得绝对路径
strOldName = strRawPath;
//strOldName.append(winFindData.cFileName);
filePath = strRawPath;
string fileName = strOldName + winFindData.cFileName;
//string strNewName = strOldName;
string imgname = winFindData.cFileName;
meanValue = calculate(fileName);
opt(fileName, imgname, meanValue);
//return fileName, filePath, imgname;
}
FindClose(hTemp);
}
void rename(const string &strPath, const string &strPathroot)
{
string fileName, filePath;
double meanValue;
string strRawPath = strPath;//传地址
strRawPath.append("\\");//加分隔符
string strFindPath = strRawPath;//在新设一个
strFindPath.append("*.*");//在最外面的目录下查找文件
WIN32_FIND_DATAA winFindData;
HANDLE hTemp = FindFirstFileA(strFindPath.c_str(), &winFindData);//c.str是因为这个函数需要cha类型,返回找到的数据
//if (INVALID_HANDLE_VALUE == hTemp)
// return 0;
while (FindNextFileA(hTemp, &winFindData))
{
string imgname = winFindData.cFileName;
//newfilePath = strRawPath;
string fileName = strRawPath + winFindData.cFileName;
//string strNewName = strOldName;
string newfileName = strPathroot + winFindData.cFileName;
rename(fileName.c_str(), newfileName.c_str());
//return fileName, filePath, imgname;
}
FindClose(hTemp);
}
int main(int argc, char *argv[])
{
string thresholdName = "路径/threshold1";
string newthresholdName = "路径/";
rename(thresholdName, newthresholdName);
string path = "路径";
judge(path);
}