windows C++-创建图像处理的异步消息(二)

 创建图像处理网络

此部分介绍如何创建对给定目录中的每个 JPEG (.jpg) 图像执行图像处理的异步消息块网络。 网络执行以下图像处理操作:

  1. 对于 Tom 创作的任何图像,转换为灰度。

  2. 对于任何以红色作为主色的图像,移除绿色和蓝色分量,然后将其变暗。

  3. 对于任何其他图像,应用棕色调。

网络仅应用与其中一个条件匹配的第一个图像处理操作。 例如,如果图像由 Tom 创作,并且将红色作为其主色,则图像仅转换为灰度。

网络执行每个图像处理操作后,它会将图像作为位图 (.bmp) 文件保存到磁盘。

以下步骤演示如何创建实现此图像处理网络的函数,并将该网络应用于给定目录中的每个 JPEG 图像。

创建图像处理网络

// 1. 创建函数 ProcessImages,它会采用磁盘上某个目录的名称。void ProcessImages(const wstring& directory)
{
}// 2. 在 ProcessImages 函数中,创建 countdown_event 变量。 本演练稍后会对 countdown_event 类进行介绍。
// Holds the number of active image processing operations and 
// signals to the main thread that processing is complete.
countdown_event active(0);// 3. 创建将 Bitmap 对象与其原始文件名关联的 std::map 对象。
// Maps Bitmap objects to their original file names.
map<Bitmap*, wstring> bitmap_file_names;// 4. 添加以下代码以定义图像处理网络的成员。//// Create the nodes of the network.//// Loads Bitmap objects from disk.transformer<wstring, Bitmap*> load_bitmap([&](wstring file_name) -> Bitmap* {Bitmap* bmp = new Bitmap(file_name.c_str());if (bmp != nullptr)bitmap_file_names.insert(make_pair(bmp, file_name));return bmp;});// Holds loaded Bitmap objects.unbounded_buffer<Bitmap*> loaded_bitmaps;// Converts images that are authored by Tom to grayscale.transformer<Bitmap*, Bitmap*> grayscale([](Bitmap* bmp) {return Grayscale(bmp);},nullptr,[](Bitmap* bmp) -> bool {if (bmp == nullptr)return false;// Retrieve the artist name from metadata.UINT size = bmp->GetPropertyItemSize(PropertyTagArtist);if (size == 0)// Image does not have the Artist property.return false;PropertyItem* artistProperty = (PropertyItem*) malloc(size);bmp->GetPropertyItem(PropertyTagArtist, size, artistProperty);string artist(reinterpret_cast<char*>(artistProperty->value));free(artistProperty);return (artist.find("Tom ") == 0);});// Removes the green and blue color components from images that have red as// their dominant color.transformer<Bitmap*, Bitmap*> colormask([](Bitmap* bmp) {return ColorMask(bmp, 0x00ff0000);},nullptr,[](Bitmap* bmp) -> bool { if (bmp == nullptr)return false;return (GetColorDominance(bmp) == 0x00ff0000);});// Darkens the color of the provided Bitmap object.transformer<Bitmap*, Bitmap*> darken([](Bitmap* bmp) {return Darken(bmp, 50);});// Applies sepia toning to the remaining images.transformer<Bitmap*, Bitmap*> sepiatone([](Bitmap* bmp) {return Sepiatone(bmp);},nullptr,[](Bitmap* bmp) -> bool { return bmp != nullptr; });// Saves Bitmap objects to disk.transformer<Bitmap*, Bitmap*> save_bitmap([&](Bitmap* bmp) -> Bitmap* {// Replace the file extension with .bmp.wstring file_name = bitmap_file_names[bmp];file_name.replace(file_name.rfind(L'.') + 1, 3, L"bmp");// Save the processed image.CLSID bmpClsid;GetEncoderClsid(L"image/bmp", &bmpClsid);      bmp->Save(file_name.c_str(), &bmpClsid);return bmp;});// Deletes Bitmap objects.transformer<Bitmap*, Bitmap*> delete_bitmap([](Bitmap* bmp) -> Bitmap* {      delete bmp;return nullptr;});// Decrements the event counter.call<Bitmap*> decrement([&](Bitmap* _) {      active.signal();});// 5. 添加以下代码以连接网络。
//
// Connect the network.
//   load_bitmap.link_target(&loaded_bitmaps);loaded_bitmaps.link_target(&grayscale);
loaded_bitmaps.link_target(&colormask);   
colormask.link_target(&darken);
loaded_bitmaps.link_target(&sepiatone);
loaded_bitmaps.link_target(&decrement);grayscale.link_target(&save_bitmap);
darken.link_target(&save_bitmap);
sepiatone.link_target(&save_bitmap);save_bitmap.link_target(&delete_bitmap);
delete_bitmap.link_target(&decrement);// 6. 添加以下代码以向网络头发送目录中每个 JPEG 文件的完整路径。// Traverse all files in the directory.
wstring searchPattern = directory;
searchPattern.append(L"\\*");WIN32_FIND_DATA fileFindData;
HANDLE hFind = FindFirstFile(searchPattern.c_str(), &fileFindData);
if (hFind == INVALID_HANDLE_VALUE) return;
do
{if (!(fileFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)){wstring file = fileFindData.cFileName;// Process only JPEG files.if (file.rfind(L".jpg") == file.length() - 4){// Form the full path to the file.wstring full_path(directory);full_path.append(L"\\");full_path.append(file);// Increment the count of work items.active.add_count();// Send the path name to the network.send(load_bitmap, full_path);}}
}
while (FindNextFile(hFind, &fileFindData) != 0); 
FindClose(hFind);// 7. 等待 countdown_event 变量达到零。
// Wait for all operations to finish.
active.wait();

图像网络成员

下表描述了网络的成员:

a06aca143e494df2bb35be9e5942b61b.png

loaded_bitmaps 消息缓冲区非常重要,因为作为 unbounded_buffer 对象,它可向多个接收方提供 Bitmap 对象。 当目标块接受 Bitmap 对象时,unbounded_buffer 对象不会向任何其他目标提供该 Bitmap 对象。 因此,将对象链接到 unbounded_buffer 对象的顺序非常重要。 grayscale、colormask 和 sepiatone 消息块各自都使用筛选器,以便仅接受特定 Bitmap 对象。 decrement 消息缓冲区是 loaded_bitmaps 消息缓冲区的重要目标,因为它接受其他消息缓冲区所拒绝的所有 Bitmap 对象。 需要 unbounded_buffer 对象以便按顺序传播消息。 因此,unbounded_buffer 对象会在新目标块链接到它之前阻塞,并在没有当前目标块接受该消息时接受消息。

如果应用程序需要多个消息块处理消息,而不只是第一个接受消息的消息块,则可以使用另一种消息块类型,例如 overwrite_buffer。 overwrite_buffer 类一次保存一个消息,但它会将该消息传播到其每个目标。

下表描述了网络的成员。

5ec818868ef048919c5af660a3d9c464.png

此示例中的 countdown_event 对象使图像处理网络能够在处理了所有图像后告知主应用程序。 countdown_event 类使用 concurrency::event 对象在计数器值达到零时发送信号。 主应用程序在每次将文件名发送到网络时使计数器递增。 网络终端节点在处理每个图像后使计数器递减。 在主应用程序遍历指定目录后,它会等待 countdown_event 对象发出指示其计数器已达到零的信号。

下面的示例展示了 countdown_event 类:

// A synchronization primitive that is signaled when its 
// count reaches zero.
class countdown_event
{
public:countdown_event(unsigned int count = 0): _current(static_cast<long>(count)) {// Set the event if the initial count is zero.if (_current == 0L)_event.set();}// Decrements the event counter.void signal() {if(InterlockedDecrement(&_current) == 0L) {_event.set();}}// Increments the event counter.void add_count() {if(InterlockedIncrement(&_current) == 1L) {_event.reset();}}// Blocks the current context until the event is set.void wait() {_event.wait();}private:// The current count.volatile long _current;// The event that is set when the counter reaches zero.event _event;// Disable copy constructor.countdown_event(const countdown_event&);// Disable assignment.countdown_event const & operator=(countdown_event const&);
};

 

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

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

相关文章

嵌入式项目:STM32平衡车详解 (基础知识篇) (基于STM32F103C8T6)

前言&#xff1a; 本文是基于B站草履虫编写的平衡车相关内容&#xff0c;包括模块和基础知识&#xff0c;结合代码进行讲解&#xff0c;将知识进行汇总 &#xff08;由于本篇内容较长&#xff0c;请结合目录使用) 注&#xff1a;基于开源精神&#xff0c;本文仅供学习参考 目…

Java—逻辑控制与输入输出

各位看官&#xff1a;如果您觉得这篇文章对您有帮助的话 欢迎您分享给更多人哦 感谢大家的点赞收藏评论&#xff0c;感谢您的支持&#xff01;&#xff01;&#xff01; 一.顺序结构&#xff1a; 我每天起床&#xff0c;躺在床上玩手机&#xff0c;然后吃中午饭&#xff0c;睡…

PIFA天线工作原理:【图文讲解】

1&#xff1a;什么是PIFA天线 PIFA ( Planar Inverted F-shaped Antenna)天线即平面倒F形天线&#xff0c;因为整个天线的形状像个倒写的英文字母F而得名 2&#xff1a;PIFA天线的应用 PIFA常见于手机天线设计&#xff0c;占手机内置天线的60%-80% 3&#xff1a;PIFA天线结构…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-09

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-09 目录 文章目录 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-09目录1. Can LLMs plan paths with extra hints from solvers?摘要创新点算法模型实验效果重要数据与结论 推荐阅读指数 2. Sc…

SQL第14课挑战题

1. 将两个select语句结合起来&#xff0c;以便从OrderItems表中检索产品ID(prod_id)和quantity。其中&#xff0c;一个select语句过滤数量为100的行&#xff0c;另一个select语句过滤ID以BNBG开头的产品。按产品ID对结果进行排序。 2. 重新第一题&#xff0c;仅使用单个select语…

【原创】可用于 Android Studio 的翻译插件

在不少讲解Android 开发的老师视频中会出现一个运行在Android Studio 上的翻译插件&#xff0c;感觉挺实用的。 接下来&#xff0c;我们把它安装在我们的Android Studio 上。 设置 点击右上角齿轮按钮&#xff0c;选择Settings 安装 翻译插件 输入Tanslation&#xff0c;选…

[简单实践]Noisy Print - 自制基于加性噪声模型的简易降噪器

NoisyPrint 最近在学习的过程中&#xff0c;突然想起一个在Adobe Audition中用过的功能。 为什么会想到这个功能呢&#xff0c;因为在我使用DeepFilter的过程中&#xff0c;我发现对于一些低信噪比的信号来说&#xff0c;DeepFilter很容易出现过拟合现象&#xff0c;导致音源…

低质量数据的多模态融合方法

目录 多模态融合 低质量多模态融合的核心挑战 噪声多模态数据学习 缺失模态插补 平衡多模态融合 动态多模态融合 启发式动态融合 基于注意力的动态融合 不确定性感知动态融合 论文 多模态融合 多模态融合侧重于整合多种模态的信息,以实现更准确的预测,在自动驾驶、…

08_OpenCV文字图片绘制

import cv2 import numpy as npimg cv2.imread(image0.jpg,1) font cv2.FONT_HERSHEY_SIMPLEXcv2.rectangle(img,(500,400),(200,100),(0,255,0),20) # 1 dst 2 文字内容 3 坐标 4 5 字体大小 6 color 7 粗细 8 line type cv2.putText(img,flower,(200,50),font,1,(0,0,250)…

c#-出现类型初始值设定项引发异常的解决方案

当出现该问题时&#xff0c;通常摸不着头脑&#xff0c;无法定位到该问题所在行。 我们可以找到应发异常的类&#xff0c;例如我上面类为YY_Model.DefaultConfig。 打开这个类文件&#xff0c;加一个断点&#xff0c;一行行运行&#xff0c;到哪里突然跳出该文件&#xff0c;则…

(计算机毕设)基于Vue和Spring Boot的宠物救助网站设计与实现

博主可接毕设&#xff01;&#xff01;&#xff01; 毕业设计&#xff08;论文&#xff09; 基于Vue和Spring Boot的宠物救助网站设计与实现 摘 要 随着中国互联网的迅猛发展&#xff0c;传统宠物救助领域面临着信息管理繁琐、辐射范围有限、信息传播受限、丢失宠物找回几率较…

机器学习框架(含实例说明)

机器学习框架是用于开发和部署机器学习模型的软件库和工具集。它们提供了一系列的算法、工具和基础设施&#xff0c;帮助开发者更高效地构建、训练和部署机器学习模型。以下是一些主要的机器学习框架及其详细介绍&#xff1a; 1. TensorFlow TensorFlow 是由Google开发的开源…

卫瓴科技,驶向「协同CRM」深水区

在卫瓴协同CRM的产品之上&#xff0c;能看到的不单纯是产品本身&#xff0c;即“提高转化率”这个单纯的指标&#xff0c;而更多的是在产品之中蕴含的“现代企业营销建设”的科学理念和认知。以此为基础&#xff0c;企业可以构建真正有价值且能长期驱动的品牌营销模型。 作者…

攻防世界---->sherlock

做题笔记。 下载。 单词中出现大写很可疑。因为大写最多出现在开头等。 猜测是隐写术。 进行筛选。 借助python实现 with open(C:\\Users\\Acer\\Downloads\\f590c0f99c014b01a5ab8b611b46c57c.txt, r) as file:text file.read() uppercase_letters [char for char in text…

Study-Oracle-11-ORALCE19C-ADG集群测试

一、用户及数据测试 1、主库创建tes3用户&#xff0c;创建表test_table。备库登录test3用户并查询test_table表中数据。 -- 创建用户 CREATE USER test7 IDENTIFIED BY test7;-- 给予创建会话的权限 GRANT CREATE SESSION TO test7;-- 给予创建表的权限 GRANT CREATE TABLE TO…

贴吧软件怎么切换ip

在网络使用中&#xff0c;有时我们需要切换IP地址来满足特定的需求&#xff0c;比如需要切换贴吧软件IP以进行不同的操作。本文将介绍几种贴吧切换IP地址的方法&#xff0c;帮助用户更好地管理自己的网络身份和访问权限。 1、更换网络环境‌ 通过连接到不同的Wi-Fi网络或使用移…

解决雪花ID在前端精度丢失问题

解决雪花ID在前端精度丢失问题 在现代分布式系统中&#xff0c;雪花算法&#xff08;Snowflake&#xff09;被广泛用于生成唯一的ID。这些ID通常是Long类型的整数。然而&#xff0c;当这些ID从后端传递到前端时&#xff0c;JavaScript的精度限制可能会导致精度丢失&#xff0c…

Android 电源管理各个版本的变动和限制

由于Android设备的电池容量有限&#xff0c;而用户在使用过程中会进行各种高耗电操作&#xff0c;如网络连接、屏幕亮度调节、后台程序运行等&#xff0c;因此需要通过各种省电措施来优化电池使用‌&#xff0c;延长电池续航时间&#xff0c;提高用户体验&#xff0c;并减少因电…

开源的云平台有哪些?

开源云平台为用户提供了构建、管理和运行云基础设施及应用的能力&#xff0c;同时允许社区参与开发和改进。以下是一些知名的开源云平台&#xff1a; 1. OpenStack 简介&#xff1a;OpenStack&#xff1a;一个广泛使用的开源云平台&#xff0c;它由多个组件组成&#xff0c;提…

【ubuntu】修改用户名、主机名、主文件夹名、登录名、密码

目录 1.他们是什么 2.修改方法 2.1 修改用户密码 2.2 修改主机名 2.2.1 切换到root用户 2.2.2 修改名称 2.3 修改用户名 主文件夹名 登录名 2.2.1 sudoers 2.2.2 passwd 2.2.3 shadow 2.2.4 group 2.2.5 修改主文件夹名 3.重启 1.他们是什么 &#xff08;1&#xf…