C++ 版本 对比字符图片

news/2024/10/6 4:38:45/文章来源:https://www.cnblogs.com/DINGJINXING/p/18288931
#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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/739959.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SumIf的问题

问题:进销存表数据等于同货号入库表中数据 函数公式解决:=SUMIF(入库!A:A,B3,入库!C:C)

7/8死神永生服周报第七期

1. 死神永生新闻 2. 死神永生服TNT军事基地[三] 3. 死神永生服的古代建筑之自然选择号目录死神永生新闻 死神永生服TNT军事基地[三] 死神永生服的古代建筑之自然选择号这几天又没上死神永生,主要是期末比较繁忙,因此又停了一期。。真的很抱歉。死神永生新闻前一周的治理新闻时…

两个全开源的3D模型素材下载网站源码 3D图纸模型素材 三维图形素材会员下载站源码

今天推荐两个全开源的3D模型素材下载网站源码 3D图纸模型素材 三维图形素材会员下载站源码,这两个源码完整,都是基于thinkphp内核开发的,框架稳定,带数据库,源码文件,可以直接部署使用。第一个:3D模型 图纸模型 机械模型(图纸)下载资源网站源码 thinkphp5开发原创模型(图…

win 10 使用SSH 连接

本教程建议使用win 10 、win 11 非家庭版使用 首先安装 ssh 服务端 Get-Service -Name *ssh* #查看服务ssh -V #查看ssh 版本 netstat -an |findstr :22 # 查看端口是否被监听 ipconfig # 查看本机IP ssh administrator@IP 在用户/.ssh 目录下创建文件 authorized_keys 将…

音视频录制与播放原理

图片来源于网上学习资料,零声学院!

2.基于Containerd运行时搭建Kubernetes多控制平面集群实践-腾讯云开发者社区-腾讯云

https://cloud.tencent.com/developer/article/21298462.基于Containerd运行时搭建Kubernetes多控制平面集群实践发布于 2022-09-29 19:27:531K0 举报文章被收录于专栏:全栈工程师修炼之路[TOC]0x00 前言简述 本章主要讲述,如果使用kubeadm进行安装配置K8S集群,并指定使用co…

【寻迹】二分与三分

二分与三分 二分是一种常用且非常精妙的算法。(英才计划甚至还水了一篇文章)三分法则可以用来解决单峰函数的极值以及相关问题 一、二分 二分法,在一个单调有序的集合或函数中查找一个解,每次均分为左右两部分,判断解在哪一个部分后调整上下界。每次二分都会舍弃一半区间,…

xftp实现linux服务器传输文件

1.xftp下载网址:https://www.xshell.com/zh/free-for-home-school/,下载后下一步安装即可 2.ip addr show查看ip地址,配置xftp连接服务器,找到对应路径传输文件 以上仅供参考,如有疑问,留言联系

markdowm语法Typora练习草稿

目录这是一级标题 这是一级标题 【Typora 教程】手把手教你如何用Typora撰写笔记_哔哩哔哩_bilibili 这是第一行 这是第二行 这是一个段落 这是一个段落这是粗体 这是斜体 这是删除线 这是下划线 这是高亮 格式里面有快捷键 1*2*3*4*5 x2 H2O一级分类二级分类三级分类tab 键 升…

视野修炼-技术周刊第91期 | 惊讶线条

① 漫画:浏览器的 UA 为什么这么长? ② 500+种js方法实现页面重载 ③ CSS 实现惊讶线条 ④ onefetch - 本地仓库信息查看工具 ⑤ StarFlare - 管理 Star 的项目 ⑥ 开源项目落地页模板 ⑦ 纯CSS鉴别是不是Safari浏览器 ⑧ 使用 MarsCode IDE 搭建 VitePress博客并使用 GitHub…

SpringBoot3 整合 Logback

SpringBoot3 整合 Logback 日志框架1. 默认框架实现 SpringBoot3 默认是使用 SLF4J + Logback 作为默认的日志门面和实现,但也支持其他日志系统,如 Log4j2、JUL (Java Util Logging), 这是通过所谓的日志门面实现的,开发者可以根据自己的需求选择合适的日志实现框架进行配置…

[LeetCode] 238. Product of Array Except Self

坑真的很多,首先要处理全零reduce没有值typeerror的问题。 class Solution:def productExceptSelf(self, nums: List[int]) -> List[int]:total=reduce(mul, nums)ret =[]if total == 0:try:total = reduce(mul, [x for x in nums if x != 0]) except TypeError:#default v…