首页 > 其他分享 >OpenCV实现图搜图简单案例

OpenCV实现图搜图简单案例

时间:2024-07-30 16:07:11浏览次数:10  
标签:匹配 案例 搜图 Button descriptorsTarget OpenCV QString orbDetector cv

一、概述

  使用OpenCV实现一个简单的图搜索的小功能

  特点:暴力匹配

  实现原理:

    1.将图片集合生成特征描述,并存入文件

    2.加载目标图像,并生成图像特征描述

    3.加载图像特征描述文件列表

    4.图像特征描述和集合中的特征描述列表进行匹配

    5.如果匹配成功就说明搜索有值,如果没有匹配成功说明没有搜索结果。

    

 

二、代码示例

#include "ORBImageMatch.h"

ORBImageMatch::ORBImageMatch(QWidget* parent)
    : QWidget(parent)
{
    this->setWindowTitle("图像匹配(相似度比较)");
    this->setFixedSize(QSize(320, 480));

    Button* btn1 = new Button(this);
    btn1->setText("选择第一张图");
    Button* btn2 = new Button(this);
    btn2->setText("选择第二张图");
    Button* btn3 = new Button(this);
    btn3->setText("开始匹配");
    Button* btn4 = new Button(this);
    btn4->setText("生成特征文件");
    QVBoxLayout* vLayout = new QVBoxLayout(this);
    vLayout->setAlignment(Qt::AlignTop);
    vLayout->addWidget(btn1);
    vLayout->addWidget(btn2);
    vLayout->addWidget(btn3);
    vLayout->addWidget(btn4);


    connect(btn1, &Button::clicked, [=]() {
        filePath1 = QFileDialog::getOpenFileName(this, tr("请选择图片"), "C:/Users/DBF-DEV-103/Downloads/", tr("Image Files(*.jpg *.png *.webp *.jpeg)"));
        searchImage();
        });

    connect(btn2, &Button::clicked, [=]() {
        filePath2 = QFileDialog::getOpenFileName(this, tr("请选择图片"), "C:/Users/DBF-DEV-103/Downloads/", tr("Image Files(*.jpg *.png *.webp *.jpeg)"));
        });

    connect(btn3, &Button::clicked, [=]() {
        matchImage();
        });

    //选择所有文件并生成特征
    connect(btn4, &Button::clicked, [=]() {
        // 打开文件对话框,选择目录
        QString directory = QFileDialog::getExistingDirectory(this, tr("请选择需要是生成特征的文件"),
        "C:/Users/DBF-DEV-103/Downloads",
        QFileDialog::ShowDirsOnly
        | QFileDialog::DontResolveSymlinks);

    // 检查是否选择了目录
    if (directory.isEmpty()) {
        // 用户没有选择目录
        qDebug() << "请选择目录";
        return;
    }
    //qDebug() << "directory=" << directory;
    // 获取目录下所有文件的列表
    QStringList fileList = QDir(directory).entryList(QDir::Files);
    batchGenerateImageCharacteristics(directory, fileList);
        });
}

void ORBImageMatch::matchImage() {
    // 加载目标图片和仓库图片
    cv::Mat targetImage = cv::imread(filePath1.toStdString().c_str(), cv::IMREAD_GRAYSCALE);
    cv::Mat repositoryImage = cv::imread(filePath2.toStdString().c_str(), cv::IMREAD_GRAYSCALE);

    // 初始化ORB检测器
    cv::Ptr<cv::ORB> orbDetector = cv::ORB::create();
    std::vector<cv::KeyPoint> keypointsRepository, keypointsTarget;
    cv::Mat descriptorsRepository, descriptorsTarget;

    // 检测特征点并计算描述符
    orbDetector->detectAndCompute(repositoryImage, cv::noArray(), keypointsRepository, descriptorsRepository);
    orbDetector->detectAndCompute(targetImage, cv::noArray(), keypointsTarget, descriptorsTarget);

    // 创建暴力匹配器对象
    cv::BFMatcher matcher;
    std::vector<cv::DMatch> matches;

    // 进行匹配
    matcher.match(descriptorsTarget, descriptorsRepository, matches);//对特征带你进行匹配然后比较距离

    // 根据匹配结果判断是否存在
    double minDist = 100;
    for (auto match : matches) {
        qDebug() << "distance=" << match.distance;
        if (match.distance < minDist)
            minDist = match.distance;
    }

    // 设定阈值
    if (minDist < 100) {
        qDebug() << "目标图片在仓库中存在";
    }
    else {
        qDebug() << "目标图片在仓库中不存在";
    }
    //c/c++ opencv保存特征到本地及加载本地特征并匹配相似度
}

//批量生成特征文件
void ORBImageMatch::batchGenerateImageCharacteristics(QString directory, QStringList fileList) {
    for (QString filePath : fileList) {
        qDebug() << "filePath=" << directory + "/" + filePath;
        QString imageFilePath = directory + "/" + filePath;
        cv::Mat targetImage = cv::imread(imageFilePath.toStdString().c_str(), cv::IMREAD_GRAYSCALE);
        cv::Ptr<cv::ORB> orbDetector = cv::ORB::create();
        std::vector<cv::KeyPoint> keypointsTarget;
        cv::Mat  descriptorsTarget;
        // 检测特征点并计算描述符
        orbDetector->detectAndCompute(targetImage, cv::noArray(), keypointsTarget, descriptorsTarget);
        //将得到的特征存起来
        // 创建FileStorage对象并打开文件
        QFileInfo fileInfo(filePath);
        QString fileName = fileInfo.completeBaseName(); // 返回不带扩展名的文件名
        QString mDirectory = directory + "/features/";
        QString fileFullName = "C:/Users/DBF-DEV-103/Downloads/features/" + fileName + ".yml";
        qDebug() << "fileFullName=" << fileFullName;
        cv::FileStorage fs(fileFullName.toStdString().c_str(), cv::FileStorage::WRITE);
        if (!fs.isOpened()) {
            std::cerr << "Error: 无法打开文件" << std::endl;
            return;
        }
        // 将特征存储到文件

        //fs.write(fileName.toStdString(), descriptorsTarget);
        cv::String mFileName = cv::String(fileName.toStdString());
        fs << "feature_" + mFileName << descriptorsTarget;
        // 关闭文件
        fs.release();
        std::cout << descriptorsTarget << std::endl;
    }

}

//搜索图片
void ORBImageMatch::searchImage() {
    // 加载目标图片和仓库图片
    cv::Mat targetImage = cv::imread(filePath1.toStdString().c_str(), cv::IMREAD_GRAYSCALE);

    // 初始化ORB检测器
    cv::Ptr<cv::ORB> orbDetector = cv::ORB::create();
    std::vector<cv::KeyPoint>  keypointsTarget;
    cv::Mat  descriptorsTarget;

    // 检测特征点并计算描述符
    orbDetector->detectAndCompute(targetImage, cv::noArray(), keypointsTarget, descriptorsTarget);

    // 创建暴力匹配器对象
    cv::BFMatcher matcher;
    std::vector<cv::DMatch> matches;

    //加载特征列表
    // 打开文件对话框,选择目录
    QString directory = "C:/Users/DBF-DEV-103/Downloads/features/";

    // 检查是否选择了目录
    if (directory.isEmpty()) {
        // 用户没有选择目录
        qDebug() << "请选择目录";
        return;
    }
    //qDebug() << "directory=" << directory;
    // 获取目录下所有文件的列表
    QStringList fileList = QDir(directory).entryList(QDir::Files);
    vector<QString> vectors;
    for (QString filePath : fileList) {
        QFileInfo fileInfo(filePath);
        QString fileName = fileInfo.completeBaseName(); // 返回不带扩展名的文件名
        QString fileFullName = directory + filePath;
        qDebug() << "fileFullName=" << fileFullName;
        // 初始化FileStorage对象
        cv::FileStorage fs(fileFullName.toStdString().c_str(), cv::FileStorage::READ);
        if (!fs.isOpened()) {
            qDebug() << "Failed to open " << fileFullName;
            return;
        }

        // 假设特征存储在名为"features"的节点下
        cv::Mat descriptors;
        const String feature_name = "feature_" + fileName.toStdString();
        fs[feature_name] >> descriptors;
        // 进行匹配
        matcher.match(descriptorsTarget, descriptors, matches);//对特征带你进行匹配然后比较距离
        // 根据匹配结果判断是否存在
        double minDist = 100;
        for (auto match : matches) {
            qDebug() << "distance=" << match.distance;
            if (match.distance < minDist)
                minDist = match.distance;
        }

        // 设定阈值
        if (minDist < 100) {
            //qDebug() << "目标图片在仓库中存在";
            vectors.push_back(fileFullName);
        }
        else {
            //qDebug() << "目标图片在仓库中不存在";
        }
        // 关闭FileStorage对象
        fs.release();
    }
    if (vectors.size() > 0) {
        qDebug() << "检测到相似图片";
    }
    else {
        qDebug() << "未检测到相似图片";
    }

    for (auto mPath : vectors) {
        qDebug() << "mPath=" << mPath;
    }

}
ORBImageMatch::~ORBImageMatch()
{
}

 

  

标签:匹配,案例,搜图,Button,descriptorsTarget,OpenCV,QString,orbDetector,cv
From: https://www.cnblogs.com/tony-yang-flutter/p/18332687

相关文章

  • 果宇科技与某迪公司应用布袋除尘器的管道插入式粉尘检测仪案例
    项目背景:某迪为了确保工业生产的安全、‌提高生产效率以及保护环境,‌保障工作人员的健康,该企业选购24台管道插入式粉尘检测仪,下面果宇科技小编分享管道插入式粉尘检测仪在某迪公司布袋除尘器的应用案例:技术背景与工作原理管道插入式粉尘检测仪概述:GY/VGD-100-PIL管道插入......
  • 有毒有害气体在线监测系统在大型钢铁厂的应用案例
    背景介绍钢铁产业是国民经济的重要支柱产业,涉及面广、产业关联度高、消费拉动大,在经济建设、社会发展、财政税收、国防建设以及稳定就业等方面发挥着重要作用。我国是钢铁工业大国,每年为全球供应超过一半以上的钢铁。在钢铁生产过程中,高炉、转炉和焦炉会产生大量煤气。煤气......
  • Vue3实战案例 知识点全面 推荐收藏 超详细 及附知识点解读
    最近经常用到vue中的一些常用知识点,打算系统性的对vue3知识点进行总结,方便自己查看,另外也供正在学习vue3的同学参考,本案例基本包含Vue3所有的基本知识点,欢迎参考,有问题评论区留言,谢谢。本项目主要还是四个章节目录1.项目结构创建2.页面组件的划分3.页面组件实现3.1N......
  • 使用带有 pythonKit XCODE 的嵌入式 Python,在 iOS 应用程序中与 OpenCV-python 签名不
    我根据Beewares使用指南在XCODE中将Python嵌入到我的iOS项目中https://github.com/beeware/Python-Apple-support/blob/main/USAGE.md运行时,我得到pythonKit找不到由ultralytics导入的cv2错误。当我将OpenCV-python添加到我的app_packages文件夹时......
  • 使用OpenCV实时检测不同形状的交通标志
    我正在尝试创建一个可以从摄像头检测交通标志的应用程序。然而,我在检测标志时遇到了一些困难。由于交通标志的颜色可能不同,所以我希望先检测标志的形状。我尝试先找到所有轮廓并尝试检测每个轮廓的形状。然而,标志的轮廓不够清晰,树木背景包含大量小轮廓,会影响检测。这样程......
  • opencv 目标检测之canny算法
    cannycanny的目标有3个1.低错误率检测出的边缘都是真正的边缘2.定位良好边缘上的像素点与真正的边缘上的像素点距离应该最小3.最小响应边缘只能标识一次,噪声不应该标注为边缘canny分几步1.滤掉噪声比如高斯滤波2.计算梯度比如用索贝尔算子算出梯度3.非极大值......
  • opencv 霍夫曼变换
    霍夫变换不仅可以找出图片中的直线,也可以找出圆,椭圆,三角形等等,只要你能定义出直线方程,圆形的方程等等.不得不说,现在网上的各种博客质量真的不行,网上一堆文章,乱TM瞎写,误人子弟.本身自己就没有理解的很清楚,又不去读算法实现的源码,写的云山雾罩的,越看越懵逼.霍夫......
  • opencv 为图像添加边界
    我们经常会有对图像边缘做扩展的需求.比如希望卷积后得到的矩阵大小不变希望改变图像大小,但是不改变宽高比opencv实现opencv中使用copyMakeBorder()来完成这一功能apisrc是原图像矩阵dst是新图像矩阵top/bottom/left/right是边界扩展的大小(比如5就代表5个像素)b......
  • opencv 膨胀与腐蚀
    腐蚀和膨胀Erosion/Dilationerosion/dilation,用白话说,就是让图像亮的区域收缩和扩张.原理我们定义一个卷积核矩阵.这个矩阵可以是任何形状的,但通常而言,是矩形或者圆形的.同时要定义一个锚点位置.用这个卷积核矩阵挨个地划过原始图像矩阵,同时更改锚点位置的像素值.......
  • 昇思25天学习打卡营第19天|ResNet50 图像分类案例:数据集、训练与预测可视化
    目录环境配置数据集加载数据集可视化BuildingBlockBottleneck构建ResNet50网络模型训练与评估可视化模型预测环境配置        首先指出实验环境预装的mindspore版本以及更换版本的方法。然后,它卸载了已安装的mindspore并重新安装指定的2.3.0rc1版......