热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

图像处理初级技巧(哲学)

这里只介绍初级技巧,并且多数只是一些提示,不包含代码和一些概念的详细说明。技巧一:双缓冲消除闪烁。很多初学者认为闪烁产生的原因是刷新速度太慢,这是个完全错误的认识。闪烁产生的原因是相邻的两帧或多帧之间,图像内容的差异过大。在实际编程中,

这里只介绍初级技巧,并且多数只是一些提示,不包含代码和一些概念的详细说明。 技巧一:双缓冲消除闪烁。 很多初学者认为闪烁产生的原因是刷新速度太慢,这是个完全错误的认识。 闪烁产生的原因是相邻的两帧或多帧之间,图像内容的差异过大。在实际编程中,

这里只介绍初级技巧,并且多数只是一些提示,不包含代码和一些概念的详细说明。

技巧一:双缓冲消除闪烁。

很多初学者认为闪烁产生的原因是刷新速度太慢,这是个完全错误的认识。
闪烁产生的原因是相邻的两帧或多帧之间,图像内容的差异过大。在实际编程中,这个差异的来源主要有三个:
1,windows自身对程序窗口背景的擦除,导致两帧之间插入空白帧。这个可以通过处理OnEraseBkgnd或者类似的地方来解决。
2,程序自身清除背景。这个就是双缓冲要取代的。
3,绘制过程表现。由于没有使用双缓冲,绘图的整个过程会重现在屏幕上,这种过程的重现会引起闪烁。

双缓冲技术的实质是:在后台缓冲绘制下一帧要显示的图形,绘制完成后切换到前台显示。由于前台显示的是上一次绘制的结果,对于连续运动的图像来说,两帧之间的差异很小,人感觉起来就是平滑的变化了。
这一技术的实现,请参考游戏开发和图像处理的书籍和资料。

技巧二:数据与显示分离。

这个技巧常见于图像处理程序,例如绘图软件等。
绝大多数初学者的第一个图像处理程序,把绘制好的图像保存为文件的过程,都是直接从DC中获取数据,然后转为BMP或者其他格式的。
这种方式对于一个简单的demo或者不做商业用途的小程序来说,是完全可以的。而一旦图像处理需要涉及一些复杂的算法,例如alpha融合,模糊,锐化等,这种方式就无法满足要求了。
正确的做法是:定义自己的图像数据格式(一般认为24bitBMP的格式就是很优秀的格式了,也能满足多数情况的需要),然后制定自定义格式到DC等设备的映射规则。所有的数据运算都在自己的数据结构内部完成,而结果经过映射后,显示在给定的设备上。
之所以不用DC,有四个主要原因:
1,DC是易变的。同一程序的不同部分,都拥有对DC的修改权限,甚至其他程序也会修改你程序的DC资源。
2,DC的精度是受限的。对于一个特定的图像处理算法,可能会引起数据的丢失或上溢,多次处理的结果会导致图像的色彩和形状完全失真。为了解决这个问题,包括photoshop在内的许多图像处理软件都提供了诸如48bit等高精度图形格式。
3,DC的尺寸是受限的。你可能想处理一个长宽都很大(例如,长宽都超过10k象素)的图像,但是DC的尺寸有它自己的限制,有些情况无法满足要求。
4,DC是设备相关的,在不同的桌面分辨率设置下的表现是不一致的。这个不用多说,256色/16位色/24位色/32位色下,截取同一DC内容得到的结果可能是不同的。你总不能要求使用你软件的用户必须使用你用的桌面设置吧?

这一技巧更重要的用途是在矢量图的绘制,矢量图一般使用浮点类型的数据保存图形细节信息,而以象素坐标为单位的屏幕DC对此无能为力。

技巧三:恰当的UNDO方式。

多数图像算法是不可逆的,例如模糊,为了能够undo每一步的操作,相当多的时候只能把处理前的图片保存一个备份,undo的时候直接恢复。
事实上,由于用户的操作可能非常复杂,那么这种备份的数量极有可能超过磁盘剩余空间。其实有个优化的方式:
原理:用户的操作虽然不能被有效undo,但是却可以被重现。
使用:保存原始的图片,记录每一步用户操作的细节,当需要undo到某一步的时候,从原始图片开始,依次重现用户的操作细节,直到需要的那个步骤。

这一技巧还可以通过在一些重现时间过长的复杂操作前后增加备份次数以改善性能。总的来说这是个时间换磁盘空间的技巧,多数时候也能加快程序的响应速度(毕竟内存计算比读取磁盘快不是一点半点)。

技巧四:必要的时候,汇编。

图像处理多数是耗时运算,即使1024×1024的bmp,总数据量也超过3M,对于一个需要逐象素处理的算法来说,这种数据量会占据大量的CPU时间。
为了改善这种状况,除了改进算法本身外,唯一的方法恐怕就是利用汇编了,可以通过MMX,SSE等特殊指令加快处理速度,多数情况,经过汇编优化的算法会比原始算法快2~3倍。
但是,你也必须保留原始的算法版本以支持不具备那些特有指令的CPU(例如Intel的CPU就不支持3DNow指令),并验证汇编的正确性。

技巧五:多线程和空闲时间利用。

为了在处理图像的同时,及时响应用户的操作,多线程一般而言在所难免,除了多线程本身的复杂性,这里需要提醒:在只有单个CPU的机器上,多线程只会降低你的运行速度而不是加快,如果你的处理不是那么耗时,或者用户界面响应不是那么重要,请慎重考虑为程序付出多线程的代价是否值得。

无论是游戏,还是图像处理程序,总是或多或少有些空闲时间,例如用户停止操作等等,程序可以选择使用这段时间来做一些后台处理的工作,例如把缓冲中的数据写入磁盘等。

技巧六:有计划的内存管理。

图像处理程序耗尽系统可用内存,这并不是什么新鲜事,再优秀的内存管理也不能处理内存需求超过供给的情况。这里有个致命问题,就是当用户的某个操作需要分配大量内存,而系统此时又无法满足的时候,你的程序可能连保存当前编辑状态的内存都拿不出来了。

为了避免这种情况,内存使用上要有一个有效的预算和反馈机制,事先预测可能发生的状况做好恢复准备,而不是等到系统内存告急的时候手忙脚乱。

与此同时,一些常用文件和数据的缓冲是提高效率的途径,也是内存缺乏时可以暂时释放的资源。

技巧七:看懂以上的所有技巧,如果你不能,那么你还没有为你所涉足的这个领域做好最基本的准备。

参考:http://blog.okbase.net/PanicNet/archive/3017.html

推荐阅读
  • 本文详细介绍了Java的安装、配置、运行流程以及有效的学习方法,旨在帮助初学者快速上手Java编程。 ... [详细]
  • 深入解析ESFramework中的AgileTcp组件
    本文详细介绍了ESFramework框架中AgileTcp组件的设计与实现。AgileTcp是ESFramework提供的ITcp接口的高效实现,旨在优化TCP通信的性能和结构清晰度。 ... [详细]
  • 本文详细介绍了如何解决 Microsoft SQL Server 中用户 'sa' 登录失败的问题。错误代码为 18470,提示该帐户已被禁用。我们将通过 Windows 身份验证方式登录,并启用 'sa' 帐户以恢复其访问权限。 ... [详细]
  • 深入剖析JVM垃圾回收机制
    本文详细探讨了Java虚拟机(JVM)中的垃圾回收机制,包括其意义、对象判定方法、引用类型、常见垃圾收集算法以及各种垃圾收集器的特点和工作原理。通过理解这些内容,开发人员可以更好地优化内存管理和程序性能。 ... [详细]
  • 本文档介绍了如何在Visual Studio 2010环境下,利用C#语言连接SQL Server 2008数据库,并实现基本的数据操作,如增删改查等功能。通过构建一个面向对象的数据库工具类,简化了数据库操作流程。 ... [详细]
  • 在项目中使用 Redis 时,了解其不同架构模式(如单节点、主从复制、哨兵模式和集群)对于确保系统的高可用性和扩展性至关重要。本文将详细探讨这些模式的特点和应用场景。 ... [详细]
  • KMP算法是处理字符串匹配的一种高效算法它首先用O(m)的时间对模板进行预处理,然后用O(n)的时间完成匹配。从渐进的意义上说,这样时间复 ... [详细]
  • 本文档汇总了Python编程的基础与高级面试题目,涵盖语言特性、数据结构、算法以及Web开发等多个方面,旨在帮助开发者全面掌握Python核心知识。 ... [详细]
  • 解决Hive操作无响应问题:drop table和create table的处理方法
    本文详细介绍了在Hive中执行drop table和create table命令时遇到无响应的情况,并提供了完整的解决方案。通过调整MySQL字符集编码,确保Hive数据库与MySQL之间的兼容性,从而有效解决问题。 ... [详细]
  • 深入理解小程序中的Picker组件
    Picker组件是一种从屏幕底部弹出的滚动选择器,支持多种选择模式,包括普通选择器、多列选择器、时间选择器、日期选择器和省市区选择器。本文将详细介绍Picker的各种属性及其应用场景。 ... [详细]
  • 本文详细介绍如何在 Windows 环境下安装 Ubuntu 12.04 版本的 Linux 操作系统,包括必要的软件下载、配置步骤以及注意事项。 ... [详细]
  • 序列化与反序列化是数据处理中的重要技术,特别是在网络通信和数据存储中。它们允许将复杂的数据结构转换为可传输或存储的格式,再从这些格式恢复原始数据。本文探讨了序列化与反序列化的基本概念,以及它们在不同协议模型中的角色。 ... [详细]
  • 如何在SQL Server 2008中通过Profiler跟踪特定数据库及获取客户端信息
    本文介绍如何利用SQL Server Profiler工具来监控特定数据库的操作,并获取执行这些操作的客户端计算机名和账户名。步骤包括创建新的跟踪、配置跟踪属性以及设置列筛选器以精确过滤数据。 ... [详细]
  • 本文探讨了C#语言中类的嵌套使用,特别是当嵌套类作为方法参数时,其内部状态是否会因方法调用而发生改变的问题。通过实例分析,详细说明了引用类型在不同情况下的行为。 ... [详细]
  • 本文探讨了Hive作业中Map任务数量的确定方式,主要涉及HiveInputFormat和CombineHiveInputFormat两种InputFormat的分片计算逻辑。通过调整相关参数,可以有效控制Map任务的数量,进而优化Hive作业的性能。 ... [详细]
author-avatar
蕊蕊宝宝妈妈_534
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有