当前位置: 首页 > article >正文

OpenCV C++ 心形雨动画

❤️ OpenCV C++ 心形雨动画 ❤️

本文将引导你使用 C++ 和 OpenCV 库创建一个可爱的心形雨动画。在这个动画中,心形会从屏幕顶部的随机位置落下,模拟下雨的效果。使用opencv定制自己的专属背景
在这里插入图片描述

目录

  1. 简介
  2. 先决条件
  3. 核心概念
  4. 实现步骤
    • 创建项目
    • 定义心形结构体
    • 绘制心形的函数
    • 主动画循环
    • 完整代码示例
  5. 编译和运行
  6. 效果展示
  7. 进一步的改进
  8. 总结

简介

我们将创建一个窗口,在窗口中,不同大小和颜色的心形会从顶部随机出现并向下飘落。这是一个有趣的小项目,可以帮助理解 OpenCV 的基本绘图、事件处理和动画循环。


先决条件

在开始之前,请确保你具备以下条件:

  • C++ 编译器:如 GCC (MinGW for Windows), Clang, 或 MSVC。
  • OpenCV 库:版本 3.x 或 4.x 已安装并配置好编译环境。
  • 基本的 C++ 知识:包括变量、循环、函数、结构体/类以及 STL (如 std::vector)。
  • 基本的 OpenCV 知识:了解 cv::Mat, cv::Point, cv::Scalar 以及窗口和绘图函数。

核心概念

  • 心形表示:我们将通过绘制一个由特定点集定义的多边形来创建一个心形。
  • 动画帧:动画是通过连续显示略有不同的图像(帧)来创建运动的错觉。
  • 对象状态:每个心形都有自己的位置、大小、颜色和下落速度。
  • 随机生成:心形的初始位置、大小、颜色和速度将随机生成,以获得更自然的效果。
  • 主循环
    1. 清除上一帧的内容(或创建新画布)。
    2. 随机生成新的心形。
    3. 更新所有现有心形的位置。
    4. 绘制所有心形到当前帧。
    5. 显示当前帧。
    6. 移除超出屏幕的心形。
    7. 短暂延迟后重复。

实现步骤

创建项目

首先,创建一个 C++ 项目,并确保你的构建系统(如 CMake 或直接使用 g++)能够链接到 OpenCV 库。

定义心形结构体

我们需要一个结构体来存储每个心形的信息:

#include <opencv2/opencv.hpp> // 主要的OpenCV头文件
#include <vector>             // 用于存储心形
#include <random>             // 用于生成随机数
#include <iostream>           // 用于输出// 定义心形的属性
struct Heart {cv::Point position; // 心形中心点当前位置int size;           // 心形大小cv::Scalar color;   // 心形颜色 (BGR格式)double speed;       // 心形下落速度
};

绘制心形的函数

我们将创建一个函数,根据给定的中心点、大小和颜色来绘制一个心形。心形可以通过 cv::fillPoly 绘制一个填充的多边形来近似。

// 绘制单个心形
void drawHeart(cv::Mat& image, cv::Point center, int size, const cv::Scalar& color) {// 定义心形轮廓点(相对于中心点)// 这些点可以调整以获得你喜欢的心形形状std::vector<cv::Point> points;points.push_back(cv::Point(center.x, center.y + size / 2));                         // 底部尖端points.push_back(cv::Point(center.x - size / 2, center.y - size / 5));              // 左侧下方点points.push_back(cv::Point(center.x - size / 2, center.y - size / 2));              // 左侧中间点points.push_back(cv::Point(center.x - size / 4, center.y - (size * 4) / 5));        // 左侧上方点(靠近凹陷处)points.push_back(cv::Point(center.x, center.y - size / 2));                         // 顶部凹陷处最低点points.push_back(cv::Point(center.x + size / 4, center.y - (size * 4) / 5));        // 右侧上方点points.push_back(cv::Point(center.x + size / 2, center.y - size / 2));              // 右侧中间点points.push_back(cv::Point(center.x + size / 2, center.y - size / 5));              // 右侧下方点// 转换成OpenCV fillPoly需要的格式const cv::Point* pts = (const cv::Point*)cv::Mat(points).data;int npts = points.size();// 绘制填充的心形cv::fillPoly(image, &pts, &npts, 1, color, cv::LINE_AA);
}

主动画循环

这是程序的核心部分,负责生成、更新、绘制和显示心形。

int main() {int windowWidth = 800;int windowHeight = 600;std::string windowName = "❤️ Heart Rain Animation ❤️";// 初始化随机数生成器std::random_device rd;std::mt19937 gen(rd());std::uniform_int_distribution<> distribX(0, windowWidth); // X坐标std::uniform_int_distribution<> distribSize(15, 40);      // 心形大小std::uniform_real_distribution<> distribSpeed(1.0, 5.0);  // 下落速度std::uniform_int_distribution<> distribColorVal(100, 255); // 用于粉色/红色系std::uniform_int_distribution<> distribSpawnChance(0, 100); // 生成新心形的概率std::vector<Heart> hearts;cv::namedWindow(windowName, cv::WINDOW_AUTOSIZE);while (true) {// 1. 创建一个黑色的画布作为当前帧cv::Mat frame = cv::Mat::zeros(windowHeight, windowWidth, CV_8UC3);// 2. 随机生成新的心形// 每帧有一定概率生成新的心形(例如15%的概率)if (distribSpawnChance(gen) < 15) { // 可以调整这个概率Heart newHeart;newHeart.position.x = distribX(gen);newHeart.position.y = 0; // 从顶部开始newHeart.size = distribSize(gen);newHeart.speed = distribSpeed(gen);// 生成粉红色系或红色的心形// BGR: (Blue, Green, Red)// 为了粉色/红色,保持蓝色通道较低,绿色适中,红色较高int blue = distribColorVal(gen) / 3; // 较低的蓝色值int green = distribColorVal(gen) / 2; // 适中的绿色值 (可以更低)int red = distribColorVal(gen);    // 较高的红色值newHeart.color = cv::Scalar(blue, green, red);hearts.push_back(newHeart);}// 3. 更新并绘制所有心形for (size_t i = 0; i < hearts.size(); ++i) {// 更新位置hearts[i].position.y += hearts[i].speed;// 绘制心形drawHeart(frame, hearts[i].position, hearts[i].size, hearts[i].color);}// 4. 移除超出屏幕的心形 (从后往前遍历以便安全删除)for (int i = hearts.size() - 1; i >= 0; --i) {if (hearts[i].position.y - hearts[i].size > windowHeight) { // 完全移出底部hearts.erase(hearts.begin() + i);}}/* 或者使用 remove_if 和 erase-remove idiom (更C++风格)hearts.erase(std::remove_if(hearts.begin(), hearts.end(),[&](const Heart& h){return h.position.y - h.size > windowHeight;}), hearts.end());*/// 5. 显示帧cv::imshow(windowName, frame);// 6. 等待按键,30毫秒延迟,如果按下ESC则退出int key = cv::waitKey(30); // 约33 FPSif (key == 27) { // ESC 键的ASCII码break;}}cv::destroyAllWindows();return 0;
}

完整代码示例

将以上片段组合起来,形成一个完整的 .cpp 文件。

#include <opencv2/opencv.hpp>
#include <vector>
#include <random>
#include <iostream> // 如果需要调试输出// 定义心形的属性
struct Heart {cv::Point position;int size;cv::Scalar color;double speed;
};// 绘制单个心形
void drawHeart(cv::Mat& image, cv::Point center, int size, const cv::Scalar& color) {std::vector<cv::Point> points;// 为了让心形看起来更正,调整y坐标的偏移int y_offset = size / 10; // 轻微向上调整心形绘制的视觉中心center.y -= y_offset;points.push_back(cv::Point(center.x, center.y + size / 2));                     points.push_back(cv::Point(center.x - size / 2, center.y - size / 5));          points.push_back(cv::Point(center.x - size / 2, center.y - size / 2));          points.push_back(cv::Point(center.x - size / 4, center.y - (size * 4) / 5));    points.push_back(cv::Point(center.x, center.y - size / 2));                     points.push_back(cv::Point(center.x + size / 4, center.y - (size * 4) / 5));    points.push_back(cv::Point(center.x + size / 2, center.y - size / 2));          points.push_back(cv::Point(center.x + size / 2, center.y - size / 5));          const cv::Point* pts = (const cv::Point*)cv::Mat(points).data;int npts = points.size();cv::fillPoly(image, &pts, &npts, 1, color, cv::LINE_AA);
}int main() {int windowWidth = 800;int windowHeight = 600;std::string windowName = "❤️ Heart Rain Animation ❤️";std::random_device rd;std::mt19937 gen(rd());std::uniform_int_distribution<> distribX(0, windowWidth);std::uniform_int_distribution<> distribSize(15, 40);std::uniform_real_distribution<> distribSpeed(1.0, 5.0);std::uniform_int_distribution<> distribColorComponent(0, 150); // 用于B和G通道std::uniform_int_distribution<> distribRedComponent(200, 255); // 用于R通道std::uniform_int_distribution<> distribSpawnChance(0, 100);std::vector<Heart> hearts;cv::namedWindow(windowName, cv::WINDOW_AUTOSIZE);while (true) {cv::Mat frame = cv::Mat::zeros(windowHeight, windowWidth, CV_8UC3);if (distribSpawnChance(gen) < 15) {Heart newHeart;newHeart.position.x = distribX(gen);newHeart.position.y = 0; // 从顶部开始,但视觉上可能需要调整到刚好在屏幕外开始newHeart.size = distribSize(gen);newHeart.speed = distribSpeed(gen);newHeart.color = cv::Scalar(distribColorComponent(gen),       // BluedistribColorComponent(gen),       // GreendistribRedComponent(gen)          // Red (ensuring it's reddish/pinkish));hearts.push_back(newHeart);}for (size_t i = 0; i < hearts.size(); ++i) {hearts[i].position.y += hearts[i].speed;drawHeart(frame, hearts[i].position, hearts[i].size, hearts[i].color);}for (int i = hearts.size() - 1; i >= 0; --i) {if (hearts[i].position.y - (hearts[i].size * 4) / 5 > windowHeight) { // 判断心形的"最高点"是否已过屏幕hearts.erase(hearts.begin() + i);}}cv::imshow(windowName, frame);int key = cv::waitKey(30);if (key == 27) {break;}}cv::destroyAllWindows();return 0;
}

编译和运行

你需要根据你的 OpenCV 安装方式来编译代码。

使用 GCC/G++ (Linux/macOS):

首先,确保你已经安装了 pkg-config 并且 OpenCV 的 .pc 文件在它的搜索路径中。

g++ your_file_name.cpp -o heart_rain $(pkg-config --cflags --libs opencv4)
# 如果你用的是OpenCV 3,可能是 opencv 而不是 opencv4
# g++ your_file_name.cpp -o heart_rain $(pkg-config --cflags --libs opencv)
./heart_rain

使用 CMake (推荐跨平台):

创建一个 CMakeLists.txt 文件:

cmake_minimum_required(VERSION 3.10)
project(HeartRain)set(CMAKE_CXX_STANDARD 11) # 或更高
set(CMAKE_CXX_STANDARD_REQUIRED True)find_package(OpenCV REQUIRED)include_directories(${OpenCV_INCLUDE_DIRS})add_executable(HeartRain your_file_name.cpp) # 替换 your_file_name.cpp
target_link_libraries(HeartRain ${OpenCV_LIBS})

然后编译:

mkdir build
cd build
cmake ..
make
./HeartRain # 或者在Windows上是 .\Debug\HeartRain.exe

效果展示

运行程序后,你会看到一个窗口,其中有各种粉红色或红色的心形从顶部随机落下,像下雨一样。

(这里可以放一张最终效果的 GIF 或截图)
(由于是文本格式,此处无法直接展示图片)


进一步的改进

这个基础版本可以有很多扩展:

  • 更精致的心形:使用贝塞尔曲线或导入 SVG 路径来绘制更平滑的心形。
  • 旋转:让心形在下落时轻微旋转。
  • 背景:添加一个漂亮的背景图片而不是纯黑色。
  • 风力效果:给心形增加水平方向的随机漂移。
  • 性能优化:对于非常大量的对象,考虑更高效的渲染或对象管理。
  • 使用Alpha透明度:如果绘制的心形有重叠,可以考虑带透明度的颜色。
  • 不同类型的心形:随机生成几种不同风格或图案的心形。

总结

通过这个小项目,我们学习了如何使用 OpenCV 和 C++ 创建一个简单的粒子动画。我们涵盖了对象的定义、绘制、随机生成、状态更新和动画循环。希望你能从中获得乐趣,并尝试进行自己的修改和扩展!

相关文章:

OpenCV C++ 心形雨动画

❤️ OpenCV C 心形雨动画 ❤️ 本文将引导你使用 C 和 OpenCV 库创建一个可爱的心形雨动画。在这个动画中&#xff0c;心形会从屏幕顶部的随机位置落下&#xff0c;模拟下雨的效果。使用opencv定制自己的专属背景 目录 简介先决条件核心概念实现步骤 创建项目定义心形结构…...

Fullstack 面试复习笔记:Java 基础语法 / 核心特性体系化总结

Fullstack 面试复习笔记&#xff1a;Java 基础语法 / 核心特性体系化总结 上一篇笔记&#xff1a;Fullstack 面试复习笔记&#xff1a;操作系统 / 网络 / HTTP / 设计模式梳理 目前上来说&#xff0c;这个系列的笔记本质上来说&#xff0c;是对不理解的知识点进行的一个梳理&…...

安卓Compose实现鱼骨加载中效果

安卓Compose实现鱼骨加载中效果 文章目录 安卓Compose实现鱼骨加载中效果背景与简介适用场景Compose骨架屏与传统View实现对比Shimmer动画原理简介常见问题与优化建议参考资料 本文首发地址 https://h89.cn/archives/404.html 背景与简介 在移动应用开发中&#xff0c;加载中占…...

使用qt 定义全局钩子 捕获系统的键盘事件

使用qt 定义全局钩子 捕获系统的键盘事件 即使焦点不在自定义软件上&#xff0c;也能够触发 以下待接口代码&#xff1a; class Hook :public QObject { Q_OBJECT public: Hook(); enum Type { CTRL_E, CTRL_W, SPACE, Enter, C };//自定义枚举&#xff0c;定义“修改”、“撤回…...

FreeType 字体信息检查工具 - 现代C++实现

文章目录 获取字体的版权信息工具简介主要特点1. 现代C实现2. 完整的功能3. 健壮的错误处理4. 国际化支持 使用说明技术亮点 获取字体的版权信息 #include <iostream> // 标准输入输出流库 #include <string> // 字符串处理库 #include <vector>…...

el-table 树形数据,子行数据可以异步加载

1、 <el-tableborder:header-cell-style"tableStyle?.headerCellStyle"ref"tableRef":data"tableData"row-key"id":default-expand-all"false" // 默认不展开所有树形节点:tree-props"{ children: children, hasC…...

【使用JAVA调用deepseek】实现自能回复

在Spring Boot系统中接入DeepSeek服务&#xff0c;并将其提供给用户使用&#xff0c;通常需要以下步骤&#xff1a; 一、准备工作 &#xff08;1&#xff09;注册DeepSeek开发者账号 访问DeepSeek官网&#xff0c;注册并创建应用&#xff0c;获取API Key。 API文档&#xff1…...

【Linux系列】rsync命令详解与实践

博客目录 高效文件同步的艺术&#xff1a;rsync 命令详解与实践rsync 命令解析rsync 的核心优势1. 增量传输&#xff1a;效率的革命2. 归档模式(-a)&#xff1a;保留文件所有属性3. 人性化输出(-h)与进度显示(--progress) 实际应用场景1. 文件备份与版本管理2. 跨设备同步3. 大…...

Windows系统工具:WinToolsPlus 之 SQL Server Suspect/质疑/置疑/可疑/单用户等 修复

数据库在数据库列表状态是 Suspect/质疑/置疑/可疑/单用户等 非正常状态时&#xff0c; 使用WinToolsPlus 数据库页签 先设置 数据源 &#xff0c; 选择 需要清理日志的数据库&#xff0c; 点击 Suspect/质疑/置疑/可疑/单用户 按钮即可进修复。 修复过程会有数据库服务停止和启…...

C++——智能指针 unique_ptr

unique_ptr的实现原理&#xff1a;简单粗暴的防拷贝 目录 一、使用C11中的新用法unique_ptr 二、使用c11模拟实现 三、使用c98特性实现 四、模拟实现unique_ptr 五、发现问题 一、使用C11中的新用法unique_ptr 由于限制了拷贝以及赋值 导致缺陷&#xff1a;unique_ptr管理…...

【Python训练营打卡】day43 @浙大疏锦行

DAY 43 复习日 作业&#xff1a; kaggle找到一个图像数据集&#xff0c;用cnn网络进行训练并且用grad-cam做可视化 进阶&#xff1a;并拆分成多个文件 我选择的是music_instruments 链接&#xff1a;Musical Instruments (kaggle.com) #导包 import torch import torch.nn as…...

1-【源码剖析】kafka核心概念

从今天开始开始在csdn上记录学习的笔记&#xff0c;主要包括以下几个方面&#xff1a; kafkaflinkdoris 本系列笔记主要记录Kafka学习相关的内容。在进行kafka源码学习之前&#xff0c;先介绍一下Kafka的核心概念。 消息 消息是kafka中最基本的数据单元&#xff0c;由key和…...

JavaScript中判断两个对象是否相同(所有属性的值是否都相同)

在JavaScript中&#xff0c;判断两个对象的所有属性是否相同&#xff08;包括嵌套对象&#xff09;需要深度比较&#xff08;deep comparison&#xff09;。以下是几种实现方法&#xff1a; 方法1&#xff1a;简易深度比较&#xff08;不考虑循环引用、Symbol和特殊对象&#x…...

Flask 应用的生产环境部署指南

Flask 是一个轻量级的 Python Web 应用框架&#xff0c;常用于快速开发 Web 应用或 API。然而&#xff0c;Flask 内置的开发服务器仅适用于开发和调试阶段&#xff0c;并不适合直接用于生产环境。本文将详细介绍在生产环境中部署 Flask 应用的最佳实践&#xff0c;包括使用专业…...

思科设备网络实验

一、 总体拓扑图 图 1 总体拓扑图 二、 IP地址规划 表格 1 接口地址规划 设备名称 接口/VLAN IP 功能 PC0 VLAN580 10.80.1.1 访问外网 PC1 VLAN581 10.80.2.1 访问外网 PC2 Fa0 20.80.1.100 端口镜像监控流量 PC3 VLAN585 10.80.6.1 远程登陆多层交换机0…...

Oracle OCP与MySQL OCP认证如何选?

认证本质与定位差异 Oracle OCP Oracle OCP是Oracle公司推出的旗舰级数据库专家认证&#xff0c;专注于其核心的闭源商业数据库技术体系。核心领域包括RAC&#xff08;Real Application Clusters&#xff09;高可用集群、Data Guard容灾解决方案、Exadata数据库一体机集成以及…...

AWS之数据分析

目录 数据分析产品对比 1. Amazon Athena 3. AWS Lake Formation 4. AWS Glue 5. Amazon OpenSearch Service 6. Amazon Kinesis Data Analytics 7. Amazon Redshift 8.Amazon Redshift Spectrum 搜索服务对比 核心功能与定位对比 适用场景 关键差异总结 注意事项 …...

C# Onnx 动漫人物头部检测

目录 效果 模型信息 项目 代码 下载 参考 效果 模型信息 Model Properties ------------------------- date&#xff1a;2024-10-19T12:32:20.920471 description&#xff1a;Ultralytics best model trained on /root/datasets/yolo/anime_head_detection/data.yaml au…...

【Ragflow】24.Ragflow-plus开发日志:增加分词逻辑,修复关键词检索失效问题

概述 在RagflowPlus v0.3.0 版本推出之后&#xff0c;反馈比较多的问题是&#xff1a;检索时&#xff0c;召回块显著变少了。 如上图所示&#xff0c;进行检索测试时&#xff0c;关键词相似度得分为0&#xff0c;导致混合相似度(加权相加得到)也被大幅拉低&#xff0c;低于设定…...

gin 常见中间件配置

这里主要配置 请求日志中间件、跨域中间件、trace_id 中间件、安全头中间件 一般来说&#xff0c;这个中间件的信息 就是放在 middlewares/* 里面的*.go 进行操作 ➜ middlewares git:(main) tree . ├── cors.go ├── logging.go ├── request_id.go └── securit…...

蚂蚁森林自动收能量助手:Ant_Forest_1_5_4_3绿色行动新选择

先放软件下载链接:夸克网盘下载 便捷助力绿色生活&#xff1a;蚂蚁森林收能量脚本_Ant_Forest_1_5_4_3 在倡导绿色环保的当下&#xff0c;蚂蚁森林成为众多用户践行低碳生活的热门平台。而蚂蚁森林收能量脚本_Ant_Forest_1_5_4_3 这款软件&#xff0c;为用户在蚂蚁森林的体验…...

Zookeeper 集群部署与故障转移

Zookeeper 介绍 Zookeeper 是一个开源的分布式协调服务&#xff0c;由Apache基金会维护&#xff0c;专为分布式应用提供高可用、强一致性的核心基础能力。它通过简单的树形命名空间&#xff08;称为ZNode树&#xff09;存储数据节点&#xff08;ZNode&#xff09;&#xff0c;…...

Redis最佳实践——电商应用的性能监控与告警体系设计详解

Redis 在电商应用的性能监控与告警体系设计 一、原子级监控指标深度拆解 1. 内存维度监控 核心指标&#xff1a; # 实时内存组成分析&#xff08;单位字节&#xff09; used_memory: 物理内存总量 used_memory_dataset: 数据集占用量 used_memory_overhead: 管理开销内存 us…...

区域徘徊检测算法AI智能分析网关V4助力公共场所/工厂等多场景安全升级

一、项目背景 随着数字化安全管理需求激增&#xff0c;重点场所急需强化人员异常行为监测。区域徘徊作为潜在安全威胁的早期征兆&#xff0c;例如校园围墙外的陌生逗留者&#xff0c;都可能引发安全隐患。传统人工监控模式效率低、易疏漏&#xff0c;AI智能分析网关V4的区域徘…...

修复与升级suse linux

suse linux enterprise desktop 10提示&#xff1a;xxx service failed when loaded shared lib . error ibgobject.so.2.0:no such file or directory. suse linux enterprise server 12.iso 通过第一启动项引导&#xff0c;按照如下方式直接升级解决。...

电力高空作业安全检测(2)数据集构建

数据集构建的重要性 在电力高空作业安全检测领域&#xff0c;利用 计算机视觉技术 进行安全监测需要大量的图像数据&#xff0c;这些数据需要准确标注不同的安全设备与作业人员行为。只有构建出包含真实场景的高质量数据集&#xff0c;才能通过深度学习等算法对高空作业中的潜…...

嵌入式开发之STM32学习笔记day18

STM32F103C8T6 SPI通信读写W25Q64 1 W25Q64简介 W25Qxx系列是一种低成本、小型化且易于使用的非易失性存储器&#xff08;NOR Flash&#xff09;&#xff0c;它广泛应用于需要持久化存储数据的各种场景&#xff0c;如数据存储、字库存储以及固件程序存储等。该系列存储器采用…...

[论文阅读]PPT: Backdoor Attacks on Pre-trained Models via Poisoned Prompt Tuning

PPT: Backdoor Attacks on Pre-trained Models via Poisoned Prompt Tuning PPT: Backdoor Attacks on Pre-trained Models via Poisoned Prompt Tuning | IJCAI IJCAI-22 发表于2022年的论文&#xff0c;当时大家还都在做小模型NLP的相关工作&#xff08;BERT&#xff0c;Ro…...

一键 Ubuntu、Debian、Centos 换源(阿里源、腾讯源等)

网上各种办法都不行&#xff0c;使用这个工具可以了。 我用的是腾讯云源 配置系统源 bash <(curl -sSL https://linuxmirrors.cn/main.sh)配置 docker 源 bash <(curl -sSL https://linuxmirrors.cn/docker.sh)...

汽车安全:功能安全FuSa、预期功能安全SOTIF与网络安全Cybersecurity 解析

汽车安全的三重防线&#xff1a;深入解析FuSa、SOTIF与网络安全技术 现代汽车已成为装有数千个传感器的移动计算机&#xff0c;安全挑战比传统车辆复杂百倍。 随着汽车智能化、网联化飞速发展&#xff0c;汽车电子电气架构已从简单的分布式控制系统演变为复杂的移动计算平台。现…...