首页 > 编程语言 >C++ 版本 对比字符图片

C++ 版本 对比字符图片

时间:2024-07-07 21:08:39浏览次数:16  
标签:std 字符 begin end sector int C++ 版本 cv

#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

相关文章

  • 11 个最佳 C++ IDE(和代码编辑器)
    11个最佳C++IDE(和代码编辑器)最新推荐文章于 2024-05-1215:15:24 发布lzhdim于2023-11-0716:44:00发布阅读量1.8w收藏25点赞数3文章标签:c++ide编辑器开发语言版权GitCode开源社区文章已被社区收录加入社区......
  • C++ 内存管理
    内存管理C/C++内存分布静态区(数据段)全局变量:在整个程序运行期间都存在的变量,包括没有显式声明为static的全局变量。静态局部变量:在函数内部声明为static的变量。它们在函数首次调用时初始化,并在程序整个运行期间保持其值。静态全局变量:在文件作用域中声明为static的变量......
  • 生信算法9 - 正则表达式匹配氨基酸序列、核型和字符串
    建议在Jupyter实践。1.使用正则表达式匹配指定的氨基酸序列importre#氨基酸序列seq='VSVLTMFRYAGWLDRLYMLVGTQLAAIIHGVALPLMMLI'#正则表达式匹配match=re.search(r'[A|G]W',seq)#打印match及匹配到开始位置和结束位置print(match)#<re.Matchobject;......
  • 打印100以内所有能被3整除的数,每5个数打印一行(devC++)
     今天让我们来学习如何利用C语言,在运行框中打印100以内所有能被3整除的数,每五个数打印一行。 首先,我们需要定义两个变量,其中n表示1~100的数字,m表示3的倍数的个数。然后利用一个for循环,在循环中n自增,利用一个if判断语句判断是否为3的倍数,如果是,则输出在循环中再利用一个......
  • 版本控制系统
    GIT分布式版本控制系统分布式版本控制,没有中央服务器的概念,每个人都有自己的版本库,因此每个人在工作时候,不需要联网,版本库本地即可管理。既然每个人都是一个完整的版本库,同事之间如果需要协作开发,就需要找一个用于“交换文件”的中央服务器,这个服务器不存在也不影响大家干活,只......
  • SpringBoot-校园疫情防控系统-93033(免费领源码+开发文档)可做计算机毕业设计JAVA、PHP
    springboot校园疫情防控系统摘 要信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对校园疫情防控等问题,对校园疫情防控进行研究分析,然后开发设计出......
  • 基于Django+微信小程序的旅游资源信息管理系统(免费领源码+数据库)可做计算机毕业设计JA
    django广西-东盟旅游资源信息管理系统小程序摘 要在社会快速发展和人们生活水平提高的影响下,旅游产业蓬勃发展,旅游形式也变得多样化,使旅游资源信息的管理变得比过去更加困难。依照这一现实为基础,设计一个快捷而又方便的基于小程序的旅游资源信息管理系统是一项十分重要并且......
  • CorelDRAW2024免费版本下载!设计达人的必备利器!
    大家好!......
  • 图神经网络版本的Kolmogorov Arnold(KAN)代码实现和效果对比
    MLP是多层感知器(MultilayerPerceptron)的缩写,它是一种前馈人工神经网络。MLP由至少三层节点组成:一个输入层、一个或多个隐藏层以及一个输出层。每一层的节点都与下一层的每个节点相连,并且每个连接都有一个权重。MLP通过这些权重和节点的激活函数来学习输入数据的模式。Kolmogorov......
  • 【C++深度探索】:继承(定义&&赋值兼容转换&&作用域&&派生类的默认成员函数)
    ✨                            愿随夫子天坛上,闲与仙人扫落花    ......