#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;
}