#include <iostream>
#include <opencv2/opencv.hpp>
#include <map>
#include <vector>
#include <string>
#include <set>
#include <filesystem>
namespace fs = std::filesystem;
// 计算图像中每个扇区的黑色像素数量
void calculateBlackPixelsInSectors(const cv::Mat& image, int sector, std::vector<int>& blackPixelCounts) {
cv::Mat binaryImage;
cv::threshold(image, binaryImage, 127, 255, cv::THRESH_BINARY_INV);
int height = binaryImage.rows;
int width = binaryImage.cols;
int centerX = width / 2;
int centerY = height / 2;
double angleStep = 360.0 / sector;
blackPixelCounts.resize(sector);
for (int i = 0; i < sector; ++i) {
double startAngle = i * angleStep * CV_PI / 180.0;
double endAngle = (i + 1) * angleStep * CV_PI / 180.0;
cv::Mat mask = cv::Mat::zeros(image.size(), CV_8UC1);
cv::Point2d center(centerX, centerY);
cv::ellipse(mask, center, cv::Size(width / 2, height / 2), 0, startAngle, endAngle, cv::Scalar(255), -1);
cv::bitwise_and(binaryImage, mask, mask);
blackPixelCounts[i] = cv::countNonZero(mask == 0);
}
}
// 比较两个图像的黑色像素分布
bool compareImages(const std::string& imagePath1, const std::string& imagePath2, int pixelThreshold, int sectorThreshold, int sector, double& similarityPercentage) {
cv::Mat image1 = cv::imread(imagePath1, cv::IMREAD_GRAYSCALE);
cv::Mat image2 = cv::imread(imagePath2, cv::IMREAD_GRAYSCALE);
std::vector<int> blackPixels1(sector), blackPixels2(sector);
calculateBlackPixelsInSectors(image1, sector, blackPixels1);
calculateBlackPixelsInSectors(image2, sector, blackPixels2);
std::vector<int> diff(sector);
std::transform(blackPixels1.begin(), blackPixels1.end(), blackPixels2.begin(), diff.begin(), std::minus<int>());
int numSimilarSectors = std::count_if(diff.begin(), diff.end(), [pixelThreshold](int d) { return std::abs(d) <= pixelThreshold; });
similarityPercentage = static_cast<double>(numSimilarSectors) / sector * 100;
int numExceedingSectors = std::count_if(diff.begin(), diff.end(), [pixelThreshold](int d) { return std::abs(d) > pixelThreshold; });
return numExceedingSectors <= sectorThreshold;
}
// 比较两个目录中的图像
void compareDirectories(const std::string& dirA, const std::string& dirB, int pixelThreshold, int sectorThreshold, int sector, int similarityThreshold) {
std::map<std::string, std::map<std::string, std::pair<double, bool>>> results;
std::map<std::string, std::vector<std::string>> unmatchedFilesA;
std::map<std::string, std::vector<std::string>> unmatchedFilesB;
std::vector<std::tuple<std::string, std::string, double>> highSimilarityPairs;
for (const auto& entryA : fs::directory_iterator(dirA)) {
std::string dirNameA = entryA.path().filename().string();
std::string pathA = entryA.path().string();
std::string pathB = dirB + "/" + dirNameA;
if (!fs::exists(pathB)) continue;
std::set<std::string> filesA, filesB;
for (const auto& file : fs::directory_iterator(pathA)) {
filesA.insert(file.path().filename().string());
}
for (const auto& file : fs::directory_iterator(pathB)) {
filesB.insert(file.path().filename().string());
}
std::vector<std::string> commonFiles(std::begin(filesA), std::end(filesA));
std::vector<std::string> temp(std::begin(filesB), std::end(filesB));
std::sort(commonFiles.begin(), commonFiles.end());
std::sort(temp.begin(), temp.end());
std::vector<std::string>::iterator it;
std::set_intersection(commonFiles.begin(), commonFiles.end(), temp.begin(), temp.end(), std::inserter(commonFiles, commonFiles.begin()));
for (const auto& fileName : commonFiles) {
std::string imgPathA = pathA + "/" + fileName;
std::string imgPathB = pathB + "/" + fileName;
double similarity;
bool withinThreshold = compareImages(imgPathA, imgPathB, pixelThreshold, sectorThreshold, sector, similarity);
results[dirNameA][fileName] = std::make_pair(similarity, withinThreshold);
if (similarity >= similarityThreshold) {
highSimilarityPairs.emplace_back(imgPathA, imgPathB, similarity);
}
}
std::set_difference(std::begin(filesA), std::end(filesA), std::begin(commonFiles), std::end(commonFiles), std::inserter(unmatchedFilesA[dirNameA], unmatchedFilesA[dirNameA].end()));
std::set_difference(std::begin(filesB), std::end(filesB), std::begin(commonFiles), std::end(commonFiles), std::inserter(unmatchedFilesB[dirNameA], unmatchedFilesB[dirNameA].end()));
}
// 输出结果
for (const auto& pair : results) {
std::cout << "Directory: " << pair.first << std::endl;
for (const auto& filePair : pair.second) {
std::cout << " File: " << filePair.first << ", Similarity: " << filePair.second.first << "%, Within Threshold: " << (filePair.second.second ? "true" : "false") << std::endl;
}
}
// 输出未匹配的文件
if (!unmatchedFilesA.empty()) {
std::cout << "\nUnmatched files in " << dirA << ":" << std::endl;
for (const auto& pair : unmatchedFilesA) {
std::cout << " Directory: " << pair.first << std::endl;
for (const auto& fileName : pair.second) {
std::cout << " File: " << fileName << std::endl;
}
}
}
if (!unmatchedFilesB.empty()) {
std::cout << "\nUnmatched files in " << dirB << ":" << std::endl;
for (const auto& pair : unmatchedFilesB) {
std::cout << " Directory: " << pair.first << std::endl;
for (const auto& fileName : pair.second) {
std::cout << " File: " << fileName << std::endl;
}
}
}
// 输出高相似度的图片对
if (!highSimilarityPairs.empty()) {
std::cout << "\nHigh Similarity Pairs:" << std::endl;
for (const auto& tuple : highSimilarityPairs) {
std::string imgA, imgB;
double sim;
std::tie(imgA, imgB, sim) = tuple;
std::cout << " Pair: " << fs::path(imgA).filename() << " and " << fs::path(imgB).filename() << ", Similarity: " << sim << "%" << std::endl;
}
}
}
int main() {
std::string dirA = "C:/Code/diifFont/imgA";
std::string dirB = "C:/Code/diifFont/imgB";
int pixelThreshold = 50;
int sectorThreshold = 5;
int sector = 72;
int similarityThreshold = 70;
compareDirectories(dirA, dirB, pixelThreshold, sectorThreshold, sector, similarityThreshold);
return 0;
}
标签:std,字符,begin,end,sector,int,C++,版本,cv
From: https://www.cnblogs.com/DINGJINXING/p/18288931