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

news2024/11/23 7:46:02

 创建图像处理网络

此部分介绍如何创建对给定目录中的每个 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.coloradmin.cn/o/2198193.html

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

相关文章

MCU 移值FreeRTOS:【图文+源代码】

1&#xff1a;裸机程序执行 在裸机程序中&#xff0c;对于简单的方式&#xff0c;经常采用查询方式&#xff0c;即一件事完成后&#xff0c;再去完成另一件事&#xff0c;按照顺序执行&#xff0c;这种执行导致当有紧急情况时&#xff0c;可能会得不到处理。对于更复杂的程序&…

pymupdf 解析 PDF

使用大模型处理文档时&#xff0c;需要对二进制格式的文档进转解析提取文字和图片&#xff0c;本文使用 pymupdf 开源库&#xff0c;对 PDF 进行解析提取文字和图片。 安装依赖 首先安装 pymupdf 依赖 pymupdf4llm0.0.17 pymupdf1.24.10 apscheduler3.10.4PDF 转 Markdown …

MyBatis-Plus 之 typeHandler 的使用

一、typeHandler 的使用 1、存储json格式字段 如果字段需要存储为json格式&#xff0c;可以使用JacksonTypeHandler处理器。使用方式非常简单&#xff0c;如下所示&#xff1a; 在domain实体类里面要加上&#xff0c;两个注解 TableName(autoResultMap true) 表示自动…

等级保护等保资料原件合集(word源资料)

第二章 系统定级与安全域 2.1 系统定级 2.1.1 不同等级的安全保护能力 2.1.2 重要信息系统 2.1.3 定级参考 2.2 安全域定义 2.2.1 安全域定义方法 2.2.2 安全域等级描述 第三章 实施方案设计 3.1 三级等保要求 3.2 基本要求的详细技术要求 3.2.1 物理安全 3.2.2 网…

非线性关卡设计

【GDC】如何设计完全非线性的单人关卡_DOOM (bilibili.com) 本文章算是此视频的简单笔记&#xff0c;更详细还请看视频 设计完全非线性关卡强调自由移动和沙盒式玩法&#xff0c;鼓励玩家进行不可预测的移动和空间探索。讲解者分享了设计此类关卡的具体步骤&#xff0c;包括明…

element ui 使用

文章目录 element ui1.组件内部传值使用说明&#xff1a;当我们在app组件中使用movie组件&#xff0c;我们希望movie组件的内容是由app组件来定义&#xff0c;就可以使用prop关键字1.在app组件中导入movie组件并且使用2.在movie中写死数据测试3.使用date测试4.使用props 2.elem…

排序--DS

1. 排序 所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 #稳定性&#xff1a; 假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&#xff0c;若经过排序&#xff0c;这些记录…

CentOS 7 yum命令报错...

例如 yum install wget 可以看到是报错的 解决方案 对系统本身的 yum 源进行备份 进入源目录 cd /etc/yum.repos.d/备份 sudo cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup下载阿里云 CentOS 7 镜像源配置文件 sudo curl -o /etc/yum…

安装R和RStudio:开始你的数据分析之旅

数据分析是当今世界中一个非常热门的领域&#xff0c;而R语言是进行数据分析的强大工具之一。R是一种编程语言和软件环境&#xff0c;用于统计计算和图形表示。RStudio是一个集成开发环境&#xff08;IDE&#xff09;&#xff0c;它为R语言提供了一个更加友好和高效的工作环境。…

Java | Leetcode Java题解之第464题我能赢吗

题目&#xff1a; 题解&#xff1a; class Solution {Map<Integer, Boolean> memo new HashMap<Integer, Boolean>();public boolean canIWin(int maxChoosableInteger, int desiredTotal) {if ((1 maxChoosableInteger) * (maxChoosableInteger) / 2 < desi…

github创建仓库并本地使用流程,以及问题src refspec xxx does not match any

1.在 GitHub 上创建一个新仓库 登录你的 GitHub 账户。 点击右上角的 “” 按钮&#xff0c;然后选择 “New repository”。 填写仓库名称&#xff08;如 my-repo&#xff09;。 &#xff08;可选&#xff09;添加描述&#xff0c;选择是否公开或私有仓库。 &#xff08;可选&…

山羊检测系统源码分享

山羊检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision 研究…

探索 Python 高精度计算的奥秘:mpmath 库全解析

文章目录 探索 Python 高精度计算的奥秘&#xff1a;mpmath 库全解析背景&#xff1a;为何选择 mpmath&#xff1f;第二部分&#xff1a;mpmath 是什么&#xff1f;第三部分&#xff1a;如何安装 mpmath&#xff1f;第四部分&#xff1a;mpmath 函数使用示例第五部分&#xff1…

钢筋计:实时监测技术优化施工安全

在现代建筑工程中&#xff0c;钢筋作为结构支撑的关键材料&#xff0c;其状态直接关系到工程的安全性和耐久性。钢筋计作为一种监测工具&#xff0c;能够实时测量钢筋混凝土结构中的钢筋应力&#xff0c;从而为施工安全提供了科学依据。 了解钢筋计的原理及应用是优化施工安全的…

《恋与深空》陷抄袭争议,但不影响它登顶App Store畅销总榜

伴随着《恋与深空》全新混池而来的&#xff0c;是文案疑似抄袭的负面新闻。 9月23日&#xff0c;《恋与深空》上线了第一个国风混池“欲揽旖旎色”&#xff0c;但比玩家的夸奖与反馈更先来的&#xff0c;是男主角之一秦彻的剧情文案抄袭的争议&#xff0c;#恋与深空 抄袭#火速…

Java 表单提交:如何像 PHP 和 Python 一样简单?

在 Java 中&#xff0c;处理表单提交通常与 PHP 或 Python 中类似&#xff0c;但由于 Java 是一种强类型语言&#xff0c;处理表单提交涉及更多配置和设置。然而我将通过一些现代框架&#xff08;如 Spring Boot&#xff09;&#xff0c;Java 可以实现和 PHP、Python 一样简便的…

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…

前端vue-配置基地址并发送请求

1.首先&#xff0c;在HBuilder的终端下载安装luch-request 2.创建一个目录utils&#xff0c;以及下面的http.js文件&#xff0c;导入安装包&#xff0c;在new一下request&#xff0c;配置接口的基地址 3.在测试文件目录里面进行测试&#xff0c;看看请求能否发送成功&#xff…

自主主权身份在企业中的作用

随着个人数据日益商品化和集中化&#xff0c;个人重新掌控身份的需求从未如此迫切。 与此同时&#xff0c;企业使用的传统身份系统往往会将敏感信息暴露于不必要的风险中&#xff0c;使用户和组织都容易受到数据泄露和隐私侵犯。 但是&#xff0c;对于当前创建这些无尽的身份…

【3dgs】3DGS**(3D Geometry Sensing)与 **NeRF**(Neural Radiance Fields)对比

以下是 3DGS&#xff08;3D Geometry Sensing&#xff09;与 NeRF&#xff08;Neural Radiance Fields&#xff09;对比表格&#xff1a; 更加详细的资料&#xff0c;轻参考&#xff1a; NERF/3DGS 对比维度3DGS (3D Geometry Sensing)NeRF (Neural Radiance Fields)基本原理…