C++ 版本 对比字符图片

#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;
}
posted @ 2024-07-07 21:07  Ding-yixia  阅读(22)  评论(0编辑  收藏  举报