C++结合OpenCV进行图像处理与分类

news2024/11/18 10:21:36

⭐️我叫忆_恒心,一名喜欢书写博客的在读研究生👨‍🎓。
如果觉得本文能帮到您,麻烦点个赞👍呗!

近期会不断在专栏里进行更新讲解博客~~~ 有什么问题的小伙伴 欢迎留言提问欧,喜欢的小伙伴给个三连支持一下呗。👍⭐️❤️
Qt5.9专栏定期更新Qt的一些项目Demo
项目与比赛专栏定期更新比赛的一些心得面试项目常被问到的知识点。

在这里插入图片描述

一、引言

在当今数字化时代,图像处理技术在各个领域得到了广泛应用。无论是自动驾驶、医学影像分析,还是安防监控、虚拟现实,图像处理都扮演着重要角色。OpenCV(Open Source Computer Vision Library)作为一个开源的计算机视觉库,提供了丰富的图像处理函数和工具,使得图像处理变得更加简单和高效。本文将介绍如何使用C++结合OpenCV进行基础的图像处理操作。
在这里插入图片描述

二、 安装OpenCV

Windows系统详细的环境安装,可以参考我之前写的这一篇文章。
VS2019中配置C++ OpenCV 4.5.4完整指南

在使用OpenCV之前,我们需要先在开发环境中安装OpenCV库。以下是Windows和Ubuntu系统中安装OpenCV的基本步骤:

1. Windows系统:

  1. 下载OpenCV安装包:OpenCV官网
  2. 解压安装包到指定目录。
  3. 配置环境变量,将OpenCV的bin目录添加到系统的PATH中。
  4. 在C++项目中添加OpenCV库的包含路径和库文件路径。

2. Ubuntu系统:

sudo apt update
sudo apt install libopencv-dev

三、 图像读取与显示

首先,我们来看一个简单的图像读取与显示的示例程序:

#include <opencv2/opencv.hpp>
#include <iostream>

int main() {
    // 读取图像
    cv::Mat image = cv::imread("example.jpg");
    
    // 检查图像是否读取成功
    if(image.empty()) {
        std::cout << "无法打开图像文件" << std::endl;
        return -1;
    }
    
    // 显示图像
    cv::imshow("Display Image", image);
    cv::waitKey(0); // 等待按键按下
    
    return 0;
}

在这个示例中,我们使用cv::imread函数读取一张图像,并使用cv::imshow函数显示图像。cv::waitKey(0)函数用于等待用户按键,以便窗口不会立即关闭。

四、 图像预处理

图像预处理是图像处理中的重要步骤,包括图像的灰度化、二值化、平滑处理等。以下是一个简单的图像预处理示例:

#include <opencv2/opencv.hpp>
#include <iostream>

int main() {
    cv::Mat image = cv::imread("example.jpg", cv::IMREAD_GRAYSCALE); // 读取灰度图像

    if(image.empty()) {
        std::cout << "无法打开图像文件" << std::endl;
        return -1;
    }

    cv::Mat blurredImage;
    cv::GaussianBlur(image, blurredImage, cv::Size(5, 5), 1.5); // 高斯模糊处理

    cv::imshow("Original Image", image);
    cv::imshow("Blurred Image", blurredImage);
    cv::waitKey(0);
    
    return 0;
}

在这个示例中,我们使用cv::imread函数以灰度模式读取图像,并使用cv::GaussianBlur函数对图像进行高斯模糊处理。

五、图像形状检测

OpenCV还提供了丰富的形状检测功能,例如边缘检测和轮廓检测。以下是一个简单的边缘检测示例:

#include <opencv2/opencv.hpp>
#include <iostream>

int main() {
    cv::Mat image = cv::imread("example.jpg", cv::IMREAD_GRAYSCALE);
    
    if(image.empty()) {
        std::cout << "无法打开图像文件" << std::endl;
        return -1;
    }

    cv::Mat edges;
    cv::Canny(image, edges, 50, 150); // Canny边缘检测

    cv::imshow("Edges", edges);
    cv::waitKey(0);
    
    return 0;
}

在这个示例中,我们使用cv::Canny函数进行边缘检测,并显示结果图像。

六、图像分类

图像分类是计算机视觉中的重要任务,常用于自动驾驶、安防监控、医疗诊断等领域。通过对图像内容进行分类,我们可以实现对不同类别物体的识别和区分。

1.1 使用Bag of Words (BOW)算法进行图像分类

Bag of Words (BOW)算法是一种经典的图像分类方法,通过将图像表示为特征词袋进行分类。下面是使用OpenCV和C++实现BOW算法进行图像分类的示例代码。

1.2 环境准备

首先,确保已安装OpenCV库,并配置好C++开发环境。需要安装额外的库如opencv_contrib,以便使用BOW相关模块。

1.3 示例代码

以下是实现BOW算法进行图像分类的代码:

#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/ml.hpp>
#include <iostream>
#include <vector>

using namespace cv;
using namespace cv::ml;
using namespace std;
using namespace cv::xfeatures2d;

void extractFeatures(const vector<string>& imagePaths, vector<Mat>& features, Ptr<SIFT> detector) {
    for (const auto& path : imagePaths) {
        Mat image = imread(path, IMREAD_GRAYSCALE);
        vector<KeyPoint> keypoints;
        Mat descriptors;
        detector->detectAndCompute(image, noArray(), keypoints, descriptors);
        features.push_back(descriptors);
    }
}

int main() {
    // 图像路径
    vector<string> trainImages = {"image1.jpg", "image2.jpg", "image3.jpg"};
    vector<string> testImages = {"test1.jpg", "test2.jpg"};

    // 创建SIFT特征检测器
    Ptr<SIFT> detector = SIFT::create();

    // 提取训练集特征
    vector<Mat> trainFeatures;
    extractFeatures(trainImages, trainFeatures, detector);

    // 聚类,创建词典
    BOWKMeansTrainer bowTrainer(100); // 词典大小
    for (const auto& feature : trainFeatures) {
        bowTrainer.add(feature);
    }
    Mat dictionary = bowTrainer.cluster();

    // 创建BOW图像描述器
    Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("FlannBased");
    BOWImgDescriptorExtractor bowDE(detector, matcher);
    bowDE.setVocabulary(dictionary);

    // 训练分类器
    Ptr<SVM> svm = SVM::create();
    Mat trainData, labels;
    for (size_t i = 0; i < trainImages.size(); ++i) {
        Mat bowDescriptor;
        bowDE.compute(imread(trainImages[i], IMREAD_GRAYSCALE), bowDescriptor);
        trainData.push_back(bowDescriptor);
        labels.push_back((float)i); // 假设每个图像都有不同的标签
    }
    svm->train(trainData, ROW_SAMPLE, labels);

    // 测试分类器
    for (const auto& path : testImages) {
        Mat testImage = imread(path, IMREAD_GRAYSCALE);
        Mat bowDescriptor;
        bowDE.compute(testImage, bowDescriptor);
        float response = svm->predict(bowDescriptor);
        cout << "Image: " << path << " classified as: " << response << endl;
    }

    return 0;
}

result

Image: test1.jpg classified as: 0
Image: test2.jpg classified as: 1

七、适合图像分类的优秀的仓库

我可以为您提供一些图片的链接,您可以使用这些图片作为博客中的例子。以下是一些公共领域图片资源网站的链接,您可以从这些网站下载适合用于图像分类任务的图片:

  1. Pixabay - 提供大量免费图片,适用于个人和商业用途。

    • 链接: Pixabay
  2. Unsplash - 一个提供高分辨率照片的平台,所有照片均可免费使用。

    • 链接: Unsplash
  3. Pexels - 提供免费且高质量的图片,可用于商业用途,无需署名。

    • 链接: Pexels
  4. Open Images Dataset - Google 提供的一个大规模图片数据集,可用于图像识别和分类。

    • 链接: Open Images Dataset
      在这里插入图片描述
  5. MNIST Database - 手写数字的图片数据集,常用于图像分类和机器学习任务。

    • 链接: MNIST Database
      在这里插入图片描述
      在这里插入图片描述
  6. CIFAR-10 and CIFAR-100 - 包含多种类别的图片数据集,适用于图像分类。

    • 链接: CIFAR-10/CIFAR-100
  7. ImageNet - 一个非常大的图像数据库,用于视觉对象识别研究。

    • 链接: ImageNet
  8. Flickr - 通过Flickr的Creative Commons搜索,您可以找到许多可用于非商业或商业用途的图片。

    • 链接: Flickr Creative Commons
  9. Getty Images - 虽然Getty Images主要是版权图片,但它们也提供了一些免费图片的集合。

    • 链接: Getty Images
  10. NASA Image and Video Library - NASA提供的图片和视频资源,适合用于科学和教育目的。

    • 链接: NASA Image and Video Library

请注意,使用图片时,您应遵守每个网站的使用条款和版权信息。对于商业用途,建议仔细检查图片的许可证,确保合法使用。

八、 结论

通过以上步骤,我们使用C++和OpenCV实现了基于BOW算法的图像分类。本文介绍了从特征提取、词典创建到模型训练和分类的全过程。这仅仅是图像分类的入门,OpenCV还支持更多复杂的算法和深度学习模型,读者可以进一步探索,以便在实际项目中更好地应用这些技术。希望本文对您在学习和应用图像分类技术方面有所帮助。

最后,最后
如果觉得有用,麻烦三连👍⭐️❤️支持一下呀,希望这篇文章可以帮到你,你的点赞是我持续更新的动力

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人工智能任务5-高级算法工程师需要学习哪些课程与掌握哪些能力

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能的任务5-高级算法工程师需要学习哪些课程&#xff0c;需要掌握哪些能力。高级算法工程师需要掌握的算法模型有&#xff1a;人脸检测模型MTCNN&#xff0c;人脸识别方法Siamese network、center loss、softm…

在VSCode中安装python

引言 Python 是一种广泛使用的高级编程语言&#xff0c;因其易学、易用、强大而受到欢迎。它由 Guido van Rossum 于 1991 年首次发布&#xff0c;并以简洁的语法和丰富的库生态系统而著称。 以下是 Python 的一些关键特点和优势&#xff1a; 关键特点 易于学习和使用&#x…

AWS的EC2之间ping不通,服务之间不通,怎么办

AWS启动的两个EC2实例&#xff0c;互相访问不了 修改安全组规则&#xff0c;添加ICMP 流量的入站规则 参考&#xff1a;AWS的EC2之间ping不通,服务之间不通,怎么办_aws ec2同一个区域的服务器-CSDN博客

选择排序-Java版本

选择排序 算法的思想&#xff1a;java模拟 算法的思想&#xff1a; 每遍历一次就找一个最小的数 *外层 一共遍历 length-1次 总遍历次数符合等差数列 时间复杂度为O(n^2)内部查找 并 返回 数值 和 下标 java模拟 public static void selectSort(int[] arr) {for(int i 0;i<…

MyBatis拦截器使用方法

前言 MyBatis拦截器可以做的工作&#xff1a;SQL修改&#xff0c;分页操作&#xff0c;数据过滤&#xff0c;SQL执行时间性能监控等。 1. 基础介绍 1.1. 核心对象 从MyBatis代码实现的角度来看&#xff0c;MyBatis的主要的核心部件有以下几个&#xff1a; Configuration&am…

InfiniGate自研网关实现思路七

25.网关Nginx负载模型配置 通过模拟多个HTTP服务配置到 Nginx 做负载均衡&#xff0c;以学习API网关负载的配置和使用 API 网关是用于支撑分布式 RPC 接口协议转换提供 HTTP 调用的一套服务&#xff0c;那么 API 网关系统就需要可横向扩展来满足系统的吞吐量诉求。所以这里需…

如何根据业务需求,轻松挑选SSL证书?

在当今数字化时代&#xff0c;网站的安全性愈发受到重视。SSL证书作为网站安全的“守门员”&#xff0c;不仅能保护用户数据不被窃取&#xff0c;还能提升网站的信任度。但面对市场上琳琅满目的SSL证书产品&#xff0c;如何根据业务需求挑选合适的证书呢&#xff1f;今天&#…

今日份动态规划学习

主要只搞了一个这道题&#xff0c;有点摸鱼了今天晚上&#xff0c;也是来小看一下这道题吧01背包完全背包 P1941 [NOIP2014 提高组] 飞扬的小鸟 题意&#xff1a; 这题是说&#xff0c;给我们一个游戏界面&#xff0c;界面的长度为n&#xff08;水平距离&#xff09;&#x…

Java | Leetcode Java题解之第134题加油站

题目&#xff1a; 题解&#xff1a; class Solution {public int canCompleteCircuit(int[] gas, int[] cost) {int n gas.length;int i 0;while (i < n) {int sumOfGas 0, sumOfCost 0;int cnt 0;while (cnt < n) {int j (i cnt) % n;sumOfGas gas[j];sumOfCos…

【活动】程序员的核心职业素养:技术与人文并重的探索之旅

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 程序员的核心职业素养&#xff1a;技术与人文并重的探索之旅1. 持续学习与技术精…

Python Lambda函数的应用实例教程

在Python编程中&#xff0c;lambda函数是一种简洁且强大的工具&#xff0c;用于创建小型匿名函数。它们在需要快速定义简单函数时特别有用。本文将详细介绍lambda函数的语法及其多种应用实例&#xff0c;帮助读者更好地理解和使用lambda函数。 一、lambda函数的基本概念 1.1 什…

多个p标签一行展示,溢出隐藏

一开始&#xff0c;我是让div包裹多个p标签&#xff0c;并让div“flex”布局&#xff0c;且单行溢出隐藏&#xff0c;可是发现当父元素或当前元素有flex时&#xff0c;text-overflow: ellipsis;是不生效的 大多数解决办法都是&#xff0c;不要flex&#xff0c;或者给div下的每个…

计算机网络 期末复习(谢希仁版本)第6章

DNS采用UDP。 DHCP 给运行服务器软件、且位置固定的计算机指派一个永久地址&#xff0c;给运行客户端软件的计算机分配一个临时地址

数据库(25)——多表关系介绍

在项目开发中&#xff0c;进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;分析并设计表结构&#xff0c;各个表之间的结构基本上分为三种&#xff1a;一对多&#xff0c;多对多&#xff0c;一对一。 一对多 例如&#xff0c;一个学校可以有…

Web IDE 在线编辑器综合实践(Web IDE 技术探索 三)

前言 前面两篇文章&#xff0c;我们简单讲述了 WebContainer/api 、Terminal 的基本使用&#xff0c;离完备的在线代码编辑器就差一个代码编辑了。今天通过 monaco editor &#xff0c;来实现初级代码编辑功能&#xff0c;讲述的是整个应用的搭建&#xff0c;并不单独针对monac…

鸿蒙轻内核M核源码分析系列六 任务及任务调度(2)任务模块

任务是操作系统一个重要的概念&#xff0c;是竞争系统资源的最小运行单元。任务可以使用或等待CPU、使用内存空间等系统资源&#xff0c;并独立于其它任务运行。鸿蒙轻内核的任务模块可以给用户提供多个任务&#xff0c;实现任务间的切换&#xff0c;帮助用户管理业务程序流程。…

设计模式-工厂方法(创建型)

创建型-工厂方法 简单工厂 将被创建的对象称为“产品”&#xff0c;将生产“产品”对象称为“工厂”&#xff1b;如果创建的产品不多&#xff0c;且不需要生产新的产品&#xff0c;那么只需要一个工厂就可以&#xff0c;这种模式叫做“简单工厂”&#xff0c;它不属于23中设计…

【PL理论】(5) F#:递归类型 | Immutability 特性(F#中值一旦定义就不会改变)

&#x1f4ad; 写在前面&#xff1a;本文旨在探讨不可变数据结构在 F# 编程中的应用&#xff0c;特别是如何利用递归记录类型来表示和操作数值表达式。通过定义存储整数的二叉树和数值表达式的类型&#xff0c;我们将展示不可变性如何简化程序的理解和维护。文章将对比 F# 与命…

LeetCode刷题之HOT100之搜索旋转排序数组

2024/6/2 雨一直下&#xff0c;一个上午都在床上趴着看完了《百年孤独》&#xff0c;撑伞去吃了个饭&#xff0c;又回到了宿舍。打开许久未开的老电脑&#xff0c;准备做题了。《百年孤独》讲了什么&#xff0c;想表达什么&#xff0c;想给读者留下什么&#xff0c;我不知道&am…

IP黑名单与IP白名单是什么?

在IP代理使用中&#xff0c;我们经常听到黑名单与白名单两个名词&#xff0c;它们不仅提供了强大的防御机制&#xff0c;还可以灵活应对不同的安全威胁。本文将详细探讨IP黑名单和白名单在网络安全中的双重屏障作用。 一、IP黑名单和白名单定义 IP黑名单与IP白名单是网络安全中…