关于图像处理:元宵节家里煮了多少汤圆合合信息扫描全能王拍照计数一键盘点

元宵将至,新春节庆气氛浓重仍旧。厨房里,餐桌上,一碗碗热气腾腾的汤圆、皮薄馅足的饺子,织就了年节和煦幸福的画面。近期,合合信息旗下扫描全能王APP“拍照计数”性能取得宽广用户的关注。该性能基于图像AI技术,能够对图片中用户指定的指标物体进行统计,疾速“点出”出图片中的物体数量。想要大抵数清汤圆、饺子、车厘子、苹果等年货的数量,只需微微一拍,答案即可出现。 扫描全能王“拍照计数”在汤圆计数中的利用 边数边忘?“拍照计数”秒解难题 扫描全能王“拍照计数”性能不仅为节日削减了乐趣,也利用科技力量为生产、生存场景中的计数工作打造了“称手”的工具。以年货等商品盘点计数需要为例,家庭用户能够在购买水果、礼盒等年货时,应用“拍照计数”性能疾速盘点数量,商家则能够在进货、销售等环节中,利用该性能统计局部货物数量,进步工作效率。 扫描全能王“拍照计数”在苹果计数中的利用 波及计数的场景十分广泛,统计班级中的人数,盘点工厂中钢筋、整机数量,都可用到“拍照计数”。 扫描全能王团队技术人员曾在林业场景实际中发现,过来在林场进行盘点工作时,工人罕用给木材横截面刷带色彩的油漆的形式,来记录已数过的木材,有的木材能看进去曾经被刷过三种色彩的油漆。由此可见,“拍照计数”性能的推出,能够帮忙不同行业的用户在晋升计数效率的同时,防止“数到一半遗记哪些曾经数过了”的难堪地步。 AI智能图像处理优化计数体验 从技术层面看,要对图片中的物体数量进行精准统计,非常考验图像处理技术中的指标检测、指标匹配、计数统计能力。“图片指标的通用辨认、统计能力是行业面临的挑战之一。”据扫描全能王团队技术人员介绍,因为被统计对象类目繁多、形态各异,传统的产品大多须要用户手动选取物体类别后进行计数。如波及统计类别的切换,至多须要操作三次。 扫描全能王“拍照计数”在车厘子计数中的利用 在AI技术的加持下,扫描全能王智能图像处理技术可依据海量不同类型的样例,实现通用性的检测和匹配,使得“拍照计数”性能具备了场景笼罩广、模型抉择便当、主动分流的特点,可在多个场景中为用户提供一键计数的便当;在木材、钢管计数等典型的工业场景需要中,相干性能也具备精度劣势。 扫描全能王是一款智能扫描及文字辨认APP,其提供的扫描及图像处理性能可将手机、平板变为随身携带的扫描仪,自2010年公布以来,产品曾经服务了寰球200个国家、地区的上亿用户。随着AI技术的一直冲破,越来越多的智能化工具正成为人们生存中不可或缺的一部分。扫描全能王将继续翻新产品性能,为宽广用户提供更加便捷、高效的服务。

February 24, 2024 · 1 min · jiezi

关于图像处理:元宵节家里煮了多少汤圆合合信息扫描全能王拍照计数一键盘点

元宵将至,新春节庆气氛浓重仍旧。厨房里,餐桌上,一碗碗热气腾腾的汤圆、皮薄馅足的饺子,织就了年节和煦幸福的画面。近期,合合信息旗下扫描全能王APP“拍照计数”性能取得宽广用户的关注。该性能基于图像AI技术,能够对图片中用户指定的指标物体进行统计,疾速“点出”出图片中的物体数量。想要大抵数清汤圆、饺子、车厘子、苹果等年货的数量,只需微微一拍,答案即可出现。 扫描全能王“拍照计数”在汤圆计数中的利用 边数边忘?“拍照计数”秒解难题 扫描全能王“拍照计数”性能不仅为节日削减了乐趣,也利用科技力量为生产、生存场景中的计数工作打造了“称手”的工具。以年货等商品盘点计数需要为例,家庭用户能够在购买水果、礼盒等年货时,应用“拍照计数”性能疾速盘点数量,商家则能够在进货、销售等环节中,利用该性能统计局部货物数量,进步工作效率。 扫描全能王“拍照计数”在苹果计数中的利用 波及计数的场景十分广泛,统计班级中的人数,盘点工厂中钢筋、整机数量,都可用到“拍照计数”。 扫描全能王团队技术人员曾在林业场景实际中发现,过来在林场进行盘点工作时,工人罕用给木材横截面刷带色彩的油漆的形式,来记录已数过的木材,有的木材能看进去曾经被刷过三种色彩的油漆。由此可见,“拍照计数”性能的推出,能够帮忙不同行业的用户在晋升计数效率的同时,防止“数到一半遗记哪些曾经数过了”的难堪地步。 AI智能图像处理优化计数体验 从技术层面看,要对图片中的物体数量进行精准统计,非常考验图像处理技术中的指标检测、指标匹配、计数统计能力。“图片指标的通用辨认、统计能力是行业面临的挑战之一。”据扫描全能王团队技术人员介绍,因为被统计对象类目繁多、形态各异,传统的产品大多须要用户手动选取物体类别后进行计数。如波及统计类别的切换,至多须要操作三次。 扫描全能王“拍照计数”在车厘子计数中的利用 在AI技术的加持下,扫描全能王智能图像处理技术可依据海量不同类型的样例,实现通用性的检测和匹配,使得“拍照计数”性能具备了场景笼罩广、模型抉择便当、主动分流的特点,可在多个场景中为用户提供一键计数的便当;在木材、钢管计数等典型的工业场景需要中,相干性能也具备精度劣势。 扫描全能王是一款智能扫描及文字辨认APP,其提供的扫描及图像处理性能可将手机、平板变为随身携带的扫描仪,自2010年公布以来,产品曾经服务了寰球200个国家、地区的上亿用户。随着AI技术的一直冲破,越来越多的智能化工具正成为人们生存中不可或缺的一部分。扫描全能王将继续翻新产品性能,为宽广用户提供更加便捷、高效的服务。

February 23, 2024 · 1 min · jiezi

关于图像处理:暗黑系王者低照度图像增强技术解析

在低光照的夜间,摄像头采集的画面通常是一片暗淡,画面清晰度要远远低于肉眼。而随着实时音视频利用技术的倒退,咱们曾经看到了各种画质加强的视频加强技术,那么是否存在一种技术,能够使视频在低光照条件下看起来比理论状况更清晰或靠近理论状况呢? 卧室的墙和灯,在低照度加强之前和之后 一、低照度图像增强技术的利用场景低照度图像增强是指对暗光条件下拍摄的图像进行画质加强,使其变得清晰或靠近于肉眼成果。咱们总结了一些与低照度相干的强需要场景,具体如下: 1、进步夜间查看或监测的可见度在夜间条件下,监控摄像头或汽车平安摄像头的视频品质和清晰度至关重要。 夜晚的乌镇牌楼,低照度加强前后的比照  在公共场所设置监控摄像头的目标是为了监督和记录。然而,夜间视频记录在光线有余的状况下大多是光明和不清晰的,不能作为刑事案件的线索或证据提供明确和无力的反对。 而汽车平安摄像头的视频记录对于交通事故的解决至关重要,越分明的视频蕴含更多的细节,有助于交警更好更快的解决。 2、用于实时流媒体或视频聊天当波及到互联网娱乐和社交场景时,咱们心愿即便在暗光条件下也能分明的看到对方的脸。 这是产生在咱们客户上的一个实在事件。该客户是一个颇具规模的网络交友平台,有一个用户不喜爱在她的卧室里开灯再加上她自身是偏彩色的皮肤,后果她的网友在这种暗淡的环境中看不到她的脸。咱们的客户对用户放弃了高度的尊重,所以心愿可能在不开灯或光线有余的状况下也能改善用户的体验。 3、用于 AI 内容辨认的图像增强技术 咱们的 Avatar 技术可能依据输出图像对人物进行实时建模。该技术中的人脸识别、人体关键点辨认等多种和视频相干的算法都对输出图像品质有着比拟高的要求。算法可能正确的辨认到人脸和躯体地位取决于输出图像是否足够清晰。 在输出图像光明或含糊的状况下,辨认人脸和身材轮廓是十分具备挑战性的,所以最终的输入成果会受到影响。 二、传统做法与弊病为了满足用户需要,解决在光线有余及条件下视频品质低下的这些问题,咱们通过自研 AI 算法对低光照视频进行加强。 1、用传统算法来加强视频亮度低照度加强的次要作用是晋升画面的亮度,同时还要思考以下几点限度: 画面过曝:高亮度的像素不应该被适度提亮克制噪点:图像乐音不应该被放大轮廓清晰:无效信息应被最大限度地保留传统算法很难同时思考上述几点要求。深度学习办法也可用于低照度图像增强,但它在内存、CPU 和 GPU 上有肯定的耗费,其弊病如下: 模型和推理库较大计算量较大耗电 夜晚的社区走廊,在低照度加强之前和之后 2、传统算法的常见问题传统算法在进行视频低照度加强的同时,对画面中的所有内容都依照雷同的规定进行解决,容易导致画面中的亮区灰度被适度拉伸,使得画面呈现过曝。 而深度学习办法的模型个别较大,运算量大,功耗大,很难在挪动端或边缘设施上进行实时处理,笼罩机型极其无限。 三、ZEGO 低照度图像增强,成果更好1、ZEGO 低照度,补救传统算法有余为了解决传统低照度图像增强带来的问题,咱们做了以下几个方面的改良: 首先不是所有的视频像素都应该被提亮,咱们要防止适度提亮那些曾经足够亮的像素。一些视频像素是低亮度的,须要相应地提亮到不同的亮度。ZEGO 低照度算法一帧一帧的对视频进行扫描,对不同亮度的像素进行分类。 理论运行场景下不会加载深度学习模型。相同,咱们只加载 2D/3D LUT(又称查找表)。咱们离线训练了深度学习模型,并提取 2D/3D-LUTs,最初将其植入到咱们的算法中,因而咱们在达到和深度学习模型雷同成果的同时,躲避掉了其自身的一些弊病。 夕阳下的乌镇水道,在低照度加强之前和之后 2、ZEGO 低照度图像增强技术劣势 FHD 实时视频  FHD 视频是指具备高帧率的高清视频,它能给用户更好的观看体验。因为采纳了深度学习算法训练失去的 2D/3D-LUT,该算法能在保障加强品质的同时进行实时处理。 舒服天然的视觉体验 咱们置信 "少即是多 "的理念。咱们对不同亮度的区域做不同水平的解决,防止过曝,使视频看起来天然、舒服。当咱们检测到视频画面足够亮时,咱们甚至不进行任何解决。 全面笼罩挪动设施,包含低端设施 得益于离线深度学习办法和其余翻新措施,ZEGO 低照度技术即便在低端或老旧智能手机(如小米 2S 或 iPhone 4S)和物联网设施上也能有杰出的性能体现。 极其照明条件下的鲁棒性 ZEGO 低照度技术曾经在大量的极其照明状况下进行了测试,可能在极其光明或亮堂的条件下良好工作。咱们还与其余友商解决方案进行了比照测试,发现后者在极其的照明条件下会呈现炫光或闪动等异常情况。 四、ZEGO 低照度图像增强技术研发思路ZEGO 即构科技领有一支专门从事视频加强的人工智能研发团队,并且已零碎的建设了一套简单的人工智能画质加强算法。该团队多年来深耕图像处理技术,一直超过现有的技术手段,即便在极其的低照度场景,也能提供令人惊艳的画质,同时可能在边缘设施上以高分辨率、高帧率、进行实时运行。 1、轻量级的深度学习模型深度学习技术尽管能对加强低光视频起到很大的作用,但它很难在低端机型上实时运行起来。 咱们应用模型训练失去的 2D/3D LUT 并在运行阶段加载该查找表用于低照度加强。基于该查找表,算法的理论算力和内存耗费都十分小,使得低端机型也能进行实时的画质加强。 ...

September 21, 2023 · 1 min · jiezi

关于图像处理:RGB到YCbCrYUV转换

公式RGB to YCbCr Y = a * R + b * G + c * BCb = (B - Y) / dCr = (R - Y) / eYCbCr to RGB R = Y + e * CrG = Y - (a * e / b) * Cr - (c * d / b) * CbB = Y + d * Cb BT.601/JPEGBT.709BT.2020a0.2990.21260.2627b0.5870.71520.6780c0.1140.07220.0593d1.7721.85561.8814e1.4021.57481.4746d和e这两个参数是为了让Cb和Cr落在-0.5~0.5区间才引入的(使之具备与明度信号Y雷同的幅值,便于工程实现),计算方法如下:d = (1 - c) / 0.5e = (1 - a) / 0.5 ...

July 12, 2023 · 1 min · jiezi

关于图像处理:OpenVI图像超分实战篇别用GAN做超分了快来试试基于扩散模型的图像超分吧

经典图像超分辨率算法Real-ESRGAN先来看下GAN来利用到图像超分辨率的经典办法Real-ESRGAN。生成网络是ESRGAN的生成网络,放弃不变,首先用L1 loss,训练以PSRN为导向的网络,取得的模型称为Real-ESRNet,而后Real-ESRNet的网络参数进行网络初始化,同时应用 L1 loss、perceptual loss、 GAN loss损失函数,训练最终的网络Real-ESRGAN。  训练数据能够本人收集,应用进化办法,构建样本对。细节的生成能力依靠GAN的作用,GAN的生成能力的倒退进化曾经经验了多年,在此不做赘述,但从理论利用中看,对于图片生成的真实性和多样性依然有待晋升。 残缺内容请点击下方链接查看: https://developer.aliyun.com/article/1173669?utm_content=g_10... 版权申明:本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。援用

May 10, 2023 · 1 min · jiezi

关于图像处理:SLBR通过自校准的定位和背景细化来去除可见的水印

一、简要介绍 本文简要介绍了论文“Visible Watermark Removal via Self-calibrated Localization and Background Refinement ”的相干工作。在图像上叠加可见的水印,为解决版权问题提供了一种弱小的武器。古代的水印去除办法能够同时进行水印定位和背景复原,这能够看作是一个多任务学习问题。然而,现有的办法存在水印检测不残缺和复原背景的纹理品质降落的问题。 因而,作者设计了一个双阶段多任务网络来解决上述问题。粗度阶段由水印分支和背景分支组成,其中水印分支对粗略估算的掩膜进行自校准,并将校准后的掩膜传递给背景分支,重建水印区域。在细化阶段,作者整合了多层次的特色来进步水印区域的纹理品质。在两个数据集上的大量试验证实了作者所提出的办法的有效性。 二、钻研背景 随着社交媒体的激增,图像成为最风行的记录和传递信息的载体。为了爱护版权或主张所有权,各种类型的可见水印被设计并通过alpha混合叠加在背景图像上。叠加可见水印被认为是反抗攻击者的一种无效的办法。然而,利用古代水印去除技术,水印图像很可能被转换为无水印图像。水印去除基于水印图像的背景图像,是一个凋谢且具备挑战性的问题。水印能够笼罩在具备不同大小、形态、色彩和透明度的背景图像的任何地位。此外,水印通常蕴含简单的图案,如扭曲的符号、细线、暗影成果等。上述起因使得在没有提供先验常识的状况下,水印去除工作十分艰难。图1显示了带水印、无水标记图像和带水印图像的一个示例。在本文的其余部分中,作者交替应用两个术语“背景图像”和“无水印图像”。 在一些前沿工作中,须要定位水印区域的地位。在水印掩膜的领导下,水印去除相似于图像inpainting或特色匹配问题。然而,手动正文每个图像的水印掩膜是十分耗时和老本低廉的。 最近,钻研人员尝试通过深度学习办法以端到端形式解决盲水印去除问题。一些工作人员将水印去除问题表述为一个不定位水印的image-to-image的转换工作。相同,其余一些工作认为水印应该部分化,顺次或同时去除。只管这些新兴的办法获得了微小的胜利,但它们仍在致力准确和齐全地定位水印,特地是当水印具备简单的图案、不同的色彩或孤立的片段时。不精确的水印掩膜会烦扰背景图像的重建。此外,重建后的图像还存在含糊、伪影、构造扭曲等品质问题,有待进一步改良。本文提出了一种新的基于自校准定位和背景细化的水印去除网络(SLBR),该网络包含一个粗度阶段和一个细化阶段。 在粗度阶段,作者将水印定位和水印去除作为多任务学习框架中的两个工作。具体来说,作者采纳了一个U-Net构造,其中两个工作共享雷同的编码器,但有两个独立的解码器。掩膜解码器分支预测多尺度水印掩膜,通过掩膜疏导的背景加强(MBE)模块为背景解码器分支提供领导,以更好地重建无水印图像。思考到不同图像中的水印在许多方面存在很大的差别,作者设计了一个自校准掩膜细化(SMR)模块,将水印特色流传到整个特色图中,以更好地解决特定于图像的水印。在细化阶段,作者以预测的水印掩膜和粗度阶段的无水印图像作为输出,生成一个细化的无水印图像。为了充分利用粗度阶段的有用信息,作者在粗度阶段的后盾解码器分支和细化阶段的编码器之间增加了跳级连贯。思考到不同档次的特色捕捉了构造信息或纹理细节,作者在细化阶段重复应用跨档次特色交融(CFF)模块来聚合多层次编码器特色。从细化阶段失去的输入图像是最终复原的背景图像。 本文的次要奉献能够总结如下:(1)提出了一种新的跨阶段多任务网络SLBR,其跨工作信息流传技术用于水印去除工作。(2)在粗度阶段,作者设计了一个新的自校准掩膜细化(SMR)模块来校准水印掩膜,以及一个新的掩膜疏导背景加强(MBE)模块来加强背景示意。(3)在细化阶段,作者提出了一种新的跨档次特色交融(CFF)模块,该模块重复失去细化的无水印图像。在两个数据集上的(4)试验证实了作者所提办法的有效性。 三、办法介绍 给定在背景图像I上叠加水印失去的水印图像J,去除水印的指标是基于水印图像J复原无水印图像I。因为水印掩膜M通常未知,本文的办法须要同时执行水印定位和水印去除两个工作,能够在多任务学习框架下适应。 如图2所示,整个网络以从粗到细的形式设计,包含粗度阶段和细化阶段。在粗度阶段,与以往的多任务学习办法相似,作者采纳了一个共享编码器和两个宰割解码器,其中两个解码器别离负责定位水印(掩膜解码器分支)和复原背景图像(背景解码器分支)。在掩膜解码器分支中,作者设计了一个自校准的掩膜细化(SMR)模块,以进步预测的水印掩膜的品质。为了简化从掩膜解码器分支到背景解码器分支的信息流,作者采纳了一个掩膜疏导的背景加强(MBE)模块来加强背景解码器的个性。在细化阶段,作者在粗度阶段的解码器特色与细化阶段的编码器特色之间建设跳跃阶段连贯,以促成信息从粗度阶段到细化阶段的流传。为了更好地复原背景图像的构造和纹理,作者还设计了一个跨档次特色交融(CFF)模块,在细化阶段迭代聚合多层次编码器特色。3.1粗度阶段在粗度阶段,作者采纳U-Net 架构,通过跳路连贯编码器和解码器特色,如图2所示。 具体地说,作者采纳了《Blind visual motif removal from a single image.》的编码器块和解码器块的构造。水印定位和水印去除作为两个工作,它们共享所有五个编码器块和第一个解码器块。但它们有三个独立的解码器块,它们别离组成掩膜解码器分支和背景解码器分支。在掩膜解码器分支中,它装备了作者设计的自校准掩膜细化(SMR)模块,并被调配来批示水印的地位。除了从最初一个解码器块中预测的掩膜外,作者还基于其余两个解码器块的特色来预测侧输入掩膜。在后盾解码器分支中,它由掩膜疏导的背景加强(MBE)模块组成,并被调配来复原笼罩有水印的损坏的背景区域。接下来将具体介绍SMR和MBE模块。 五、总结与探讨 本文钻研了水印去除工作,开发了一种具备新的MBE、SMR和CFF模块的两阶段多任务网络,该网络能够对水印进行定位,同时复原无水印图像。在两个数据集上的大量试验验证了作者所提出的网络的优越性。

April 14, 2023 · 1 min · jiezi

关于图像处理:论文解读不和谐区域定位

一、简要介绍 不谐和区域定位的目标是在与四周背景不兼容的合成图像中定位该区域。不谐和问题次要是因为图像编辑技术产生的色彩和照明不统一。在本钻研中,作者偏向于将输出的图像转换到另一个色彩空间,以放大不谐和区域与背景之间的域差别,从而使模型更容易地辨认不谐和区域。为此,作者提出了一种由一个色彩映射模块和一个不谐和的区域定位网络组成的新框架,其中前者装备了一种新的域差别放大损失,后者能够是一个任意的定位网络。在图像协调数据集上的大量试验表明了作者设计的框架的优越性。

April 7, 2023 · 1 min · jiezi

关于图像处理:单阈值大津法

单阈值大津法大津法属于全局阈值办法中的一种,即是最大类间方差法 大津法次要原理在于会主动找出一个阈值 使得宰割后的两部分类间方差最大 实用于有双波峰的图像,大津法作为图像宰割中阈值选取的罕用算法,计算简略,不受图像亮度和对比度的影响,次要原理如下:影像的大小为M×N,将前景区域和背景区域的宰割阈值记作T,影像中像素值小于阈值T的像素个数记为N0,像素值大于阈值T的像素个数记为N1,则有: w0=N0/(M×N) w1=N1/(M×N) =w0×0+w1×1 g=w0×(0-)^2+w1×(1-)^2 其中w0为前景区域像素个数占整幅影像的比例,其像素均值为0;w1是背景区域像素个数占整幅影像的比例,其像素均值为1;为影像的总像素均值,g为类间方差,当计算出的类间方差g最大时,对应的阈值T即为最佳宰割成果的阈值。 其实比照 方差的求解公式很容易了解 最大类间方差类间方差就是把图像分成两团 两个整体 别离计算 每个整体的方差 方差1 xi就是 前景的均值u0 x均匀 就是整幅影像均值u n=1 方差2 同样而后再乘以这两局部的权重 相加即可 #include <iostream>#include <opencv2/core.hpp>#include <opencv2/highgui.hpp>#include <opencv2/imgproc.hpp>#include <opencv2\imgproc\types_c.h>#include <opencv2/highgui/highgui_c.h>#include <opencv2/opencv.hpp>#include <iostream>using namespace std;using namespace cv;double Otsu(Mat& image){ int threshold = 0; double maxVariance = 0; double w0 = 0, w1 = 0;//前景与背景像素点所占比例 double u0 = 0, u1 = 0;//前景与背景像素值均匀灰度 int histogram[256] = { 0 }; //定义一个数组 长度为256 0-255 int Num = image.cols * image.rows; //总像素个数 //统计256个bin,每个bin像素的个数 for (int i = 0; i < image.rows; i++) { const uchar* p = image.ptr<uchar>(i); for (int j = 0; j < image.cols; j++) { histogram[int(*p++)]++; //cout<<"Histogram[data[i*image.step+j]]++:;"<<histogram[int(*p++)]++<<endl; } //*p++, *和++优先级是雷同的 先解援用取出指针指向的值, //而后再将指针地址加1,指向下一个地位。也就是取值为 *p 然而这时候指针曾经指向下一个地位 } //前景像素统计 for (int i = 1; i < 256; i++) { w0 = 0; //前景像素所占比例 w1 = 0; //背景像素所占比例 u0 = 0; //前景像素灰度均值 u1 = 0; //背景像素灰度均值 for (int j = 1; j <= i; j++) { w0 = w0 + histogram[j];//以i为阈值,统计前景像素比例 u0 = u0 + j * histogram[j];//以i为阈值,统计前景像素灰度总和 } u0 = u0 / w0; w0 = w0 / Num; //Num是总像素个数 //背景像素统计 for (int j = i + 1; j <= 255; j++) { w1 = w1 + histogram[j];//以i为阈值,统计前景像素个数 u1 = u1 + j * histogram[j];//以i为阈值,统计前景像素灰度总和 histogram[j]是像素值为j的像素个数 } u1 = u1 / w1; w1 = w1 / Num; // 后面的u1是总灰度和 除以w1总个数是前景的灰度均值// 后面的w1是总个数 除以Num当前才是比例 double variance = w0 * w1 * (u1 - u0) * (u1 - u0); //以后类间方差计算 if (variance > maxVariance) { maxVariance = variance; threshold = i; } } cout << "threshold:" << threshold << endl; return threshold;}int main(){ Mat img = imread("C://Users//马亚飞//Pictures//Saved Pictures//湖人.jpg"); imshow("原图", img); Mat img1; img.copyTo(img1); cvtColor(img, img, CV_BGR2GRAY); // 把img转为灰度图 cvtColor(img1, img1, CV_BGR2GRAY); //把img1转为灰度图 double th = Otsu(img); //调用Otsu函数 失去阈值th cout << "The return value of getOstu is: " << th << endl; //输入阈值th cout << "The return value of opencv threshold is: " << threshold(img1, img1, th, 255, CV_THRESH_OTSU);//opencv已实现的大津法 for (int i = 0; i < img.rows; i++) //行循环 { uchar* data = img.ptr<uchar>(i); //获取第i行的首地址 for (int j = 0; j < img.cols; j++) //列循环 { if (data[j] <= th) data[j] = 0; else data[j] = 255; } //行解决完结 } imshow("Ostu_img", img); //cv::namedWindow("Opencv_img", CV_WINDOW_NORMAL); cv::imshow("Opencv_img", img1); //对一次大津法 的彩色或者红色局部进行掩膜 //bitwise_not(img1, img1); //这里先变反转色彩 /*Mat src = imread("D://opencvdata//0//0.png"); src.setTo(0,img1); imshow("掩膜", src);*/ waitKey(0); return 0;}(威少的黑白图还有点像利拉德)都差不多 ...

March 28, 2023 · 2 min · jiezi

关于图像处理:图像分割三边缘检测

边缘检测是指 部分信息的不连续性 比方灰度信息的渐变处称为边缘边缘检测算子分类:所谓的一阶 二阶就是 求几阶导 比方一阶就是别离对x或y方向求一阶导二阶就是 先对x 再对y求二阶导 (1)一阶 微分算子Roberts prewitt Sobel①roberts算子分为程度方向和垂直方向2x2 的滤波核 适宜解决低噪声图像和靠近45度的边缘 然而提取的边缘较粗 ②prewitt算子3x3的算子 也是分为程度方向和垂直方向 -1 -1 -1 1 1 1比 2x2的roberts算子 检测出边缘更精确 ③sobel算子与prewitt算子相比 减少了权重的概念 认为间隔以后像素点越近 对该像素影响越大3X3的算子 程度 垂直两个方向 有更强的抗噪性 (2)二阶拉普拉斯算子 属于空间锐化滤波操作 个别也用于边缘检测 小结:这种一阶和二阶导数对噪声很敏感 所以个别去除噪声 (3)其余canny算子比拟风行的边缘检测算子了 比较复杂次要是四个步骤:①高斯滤波去噪②计算图像梯度③用非极大值克制 技术解决梯度值非极大克制是一种瘦边经典算法。它克制那些梯度不够大的像素点,只保留最大的梯度,从而达到瘦边的目标(克制就是设置为0)④双阈值算法和滞后边界跟踪1)通过非极大值克制当前 可能仍然存在噪点 所以设定一个 阈值上界和阈值下界 大于阈值上界的 必然是边界在之间的 就设为候选项 (弱边界)小于阈值下界的 必然不是边界2)滞后边界跟踪当弱边缘的四周8邻域有强边缘点存在时,就将该弱边缘点变成强边缘点,以此来实现对强边缘的补充。 学习自:http://t.csdn.cn/a6Je9

March 28, 2023 · 1 min · jiezi

关于图像处理:StyleGAN-生成-AI-虚拟人脸再也不怕侵犯肖像权

什么是 StyleGANGAN 是机器学习中的生成性反抗网络,指标是合成与实在图像无奈辨别的人工样本,如图像。即扭转人脸图像中的特定特色,如姿态、脸型和发型,GAN 的次要挑战就是如何图像变得更加真切。StyleGAN 是一种基于款式的 GAN 的生成器体系结构,是一个弱小的能够管制生成图片属性的框架,它采纳了全新的生成模型,分层的属性管制,可能生成 1024×1024 分辨率的人脸图像,并且能够进行属性的准确管制与编辑,能够生成最先进的后果—高分辨率图像,看起来比以前生成的图像更实在。 如何应用 StyleGAN对于应用 StyleGAN 技术生成人脸的技术曾经开源了,已反对网红脸、明星脸、萌娃脸、超模脸、黄种人脸等图像的生成。对于 windows 中如何应用这项技术呢?首先咱们须要有 Python3 环境,这里举荐 Anaconda 集成环境,下载地址:https://www.anaconda.com/另外咱们须要装置 CUDA 10.0及以上的环境,下载地址:https://developer.nvidia.com/cuda-10.0-download-archive其次咱们须要装置 CUDA 10.0 对应的 cuDNN,我下载的是 cuDNN 7.6.4 for CUDA 10.0,下载地址:https://developer.nvidia.com/rdp/cudnn-archive最初咱们须要装置 VS2017 或 VS2019,下载地址:https://visualstudio.microsoft.com/zh-hans/vs/,装置的时候肯定勾选上 应用C++的桌面开发 下载我的项目首先咱们须要下载我的项目到本地,而后再装置我的项目所需的一些依赖即可我的项目地址:https://github.com/a312863063/generators-with-stylegan2.git如果你无奈通过 git clone 下载,也能够间接去链接外面下载压缩包,下载到本地后再解压# 下载我的项目库git clone https://github.com/a312863063/generators-with-stylegan2.git# 装置依赖pip install tensorflow-gpu==1.14.0pip install scipy==1.3.3pip install requests==2.22.0pip install Pillow==6.2.1 批改我的项目 MSVC须要关上我的项目中的文件 dnnlib/tflib/custom_ops.py,第29行所标注的 MSVC 的版本号这个根据本身电脑装置的版本进行批改便可,个别只须要批改下图的 14.16.27023 的地位即可compiler_bindir_search_path = [ 'C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.16.27023/bin/Hostx64/x64', 'C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.16.27023/bin/Hostx64/x64', 'C:/Program Files (x86)/Microsoft Visual Studio 14.0/vc/bin',] 运行我的项目只须要运行 python main.py 即可生成对应的模型的图片在 main.py 文件中,咱们能够看到,能够自定义模型和一次性生成图片的数量模型须要自行下载,下载实现后放到 networks 目录下,想生成哪种类型的图片,只有更换模型门路即可当初反对网红脸、明星脸、萌娃脸、超模脸、黄种人脸等模型,下载链接在 networks 文件夹下文本文档中def main(): os.makedirs('results/', exist_ok=True) os.makedirs('results/generate_codes/', exist_ok=True) network_pkl = 'networks/generator_star-stylegan2-config-f.pkl' # 模型地位 generate_num = 20 # 生成数量 generate_images(network_pkl, generate_num) 运行后果生成的对应后果寄存在 results 文件夹下 ...

March 20, 2023 · 1 min · jiezi

关于图像处理:Matlab常用图像处理命令108例八

文章和代码以及样例图片等相干资源,曾经归档至【Github仓库:digital-image-processing-matlab】或者公众号【AIShareLab】回复 数字图像处理 也可获取。98.roifill性能:在图像的任意区域中进行平滑插补。语法: J = roifill(I,c,r) J = roifill(I)J = roifill(I,BW) [J,BW] = roifill(...) J = roifill(x,y,I,xi,yi)[x,y,J,BW,xi,yi] = roifill(...)举例 I = imread('eight.tif');c = [222 272 300 270 221 194];r = [21 21 75 121 121 75];J = roifill(I,c,r); imshow(I)figure, imshow(J) 相干命令: roifilt2, roipoly 99.roifilt2性能:过滤敏感区域。语法: J = roifilt2(h,I,BW)J = roifilt2(I,BW,fun)J = roifilt2(I,BW,fun,P1,P2,...)举例 h = fspecial('unsharp'); J = roifilt2(h,I,BW); imshow(J) 相干命令: filter2, roipoly 100.roipoly性能:抉择一个敏感的多边形区域。语法: BW = roipoly(I,c,r)BW = roipoly(I)BW = roipoly(x,y,I,xi,yi) [BW,xi,yi] = roipoly(...)[x,y,BW,xi,yi] = roipoly(...)举例 ...

March 17, 2023 · 2 min · jiezi

关于图像处理:Matlab常用图像处理命令108例七

文章和代码以及样例图片等相干资源,曾经归档至【Github仓库:digital-image-processing-matlab】或者公众号【AIShareLab】回复 数字图像处理 也可获取。86.pixval性能:显示图像像素信息。语法: pixval on pixval off pixvalpixval(fig,option) 相干命令: impixel, improfile 87.qtdecomp性能:进行四叉树合成。语法: S = qtdecomp(I)S = qtdecomp(I,threshold)S = qtdecomp(I,threshold,mindim)S = qtdecomp(I,threshold,[mindim maxdim]) S = qtdecomp(I,fun)S = qtdecomp(I,fun,P1,P2,...)举例 I = [1 1 1 1 2 3 6 61 1 2 1 4 5 6 81 1 1 1 10 15 7 71 1 1 1 20 25 7 720 22 20 22 1 2 3 420 22 22 20 5 6 7 820 22 20 20 9 10 11 1222 22 20 20 13 14 15 16];S = qtdecomp(I,5); full(S)ans =4 0 0 0 2 0 2 00 0 0 0 0 0 0 00 0 0 0 1 1 2 00 0 0 0 1 1 0 04 0 0 0 2 0 2 00 0 0 0 0 0 0 00 0 0 0 2 0 2 00 0 0 0 0 0 0 0相干命令: qtgetblk, qtsetblk ...

March 17, 2023 · 2 min · jiezi

关于图像处理:raw照片智能处理工具DxO-PureRAW-中文激活版

高效解决raw图像,强推DxO PureRAW中文激活版,人工智能在保留细节与打消乐音之间达到了完满的均衡。DeepPRIME技术解决了您背后的这些问题,并且比您更好。您的镜头应该失去最好的校对。应用DxO专门设计的光学模块,能够主动校对设施中的缺点。复原旧的RAW文件从新开始编辑因为图像品质差,噪点或不足清晰度而搁置的旧照片。DxO PureRAW给您另一个机会。细节在于完满 DxO PureRAW 中文激活版点此 享受大幅面照片:DxO PureRAW揭示了您捕捉的每种纹理的所有细节和技巧,因而您能够享受令人难以置信的纯照片。柔和,无颗粒的散景永恒删除相机在照片的含糊区域中创立的“寄生”颗粒。DxO PureRAW为您的图像削减了令人难以置信的柔韧性。

March 16, 2023 · 1 min · jiezi

关于图像处理:Matlab常用图像处理命令108例六

文章和代码以及样例图片等相干资源,曾经归档至【Github仓库:digital-image-processing-matlab】或者公众号【AIShareLab】回复 数字图像处理 也可获取。66.imshow性能:显示图像。语法: imshow(I,n) imshow(I,[low high]) imshow(BW) imshow(X,map) imshow(RGB)imshow(...,display_option) imshow(x,y,A,...)imshow filename h = imshow(...) 相干命令: getimage, imread, iptgetpref, iptsetpref, subimage, truesize, warp 67.imwrite性能:把图像写入图形文件中。语法: imwrite(A,filename,fmt) imwrite(X,map,filename,fmt) imwrite(...,filename) imwrite(...,Param1,Val1,Param2,Val2...) 举例 imwrite(X,map,'flowers.hdf','Compression','none',...'WriteMode','append') 相干命令: imfinfo, imread 68.ind2gray性能:把检索图像转化为灰度图像。语法: I = ind2gray(X,map)举例 load treesI = ind2gray(X,map); imshow(X,map) figure,imshow(I) 相干命令: gray2ind, imshow, rgb2ntsc 69.ind2rgb性能:转化索引图像为RGB 真彩图像。语法: RGB = ind2rgb(X,map) 相干命令: ind2gray, rgb2ind 70.iptgetpref性能:获取图像处理工具箱参数设置。语法: value = iptgetpref(prefname)举例 value = iptgetpref('ImshowAxesVisible') value =off相干命令: imshow, iptsetpref 71.iptsetpref性能:设置图像处理工具箱参数。语法: iptsetpref(prefname,value)举例 iptsetpref('ImshowBorder','tight') 相干命令: imshow, iptgetpref, truesize ...

March 16, 2023 · 2 min · jiezi

关于图像处理:Matlab常用图像处理命令108例五

文章和代码以及样例图片等相干资源,曾经归档至【Github仓库:digital-image-processing-matlab】或者公众号【AIShareLab】回复 数字图像处理 也可获取。54.imcontour性能:创立图像数据的轮廓图。语法: imcontour(I,n) imcontour(I,v) imcontour(x,y,...) imcontour(...,LineSpec) [C,h] = imcontour(...)举例 I = imread('ic.tif'); imcontour(I,3) 相干命令: clabel, contour, LineSpec 55.imcrop性能:剪切图像。语法: I2 = imcrop(I)X2 = imcrop(X,map) RGB2 = imcrop(RGB) I2 = imcrop(I,rect)X2 = imcrop(X,map,rect) RGB2 = imcrop(RGB,rect) [...] = imcrop(x,y,...) [A,rect] = imcrop(...)[x,y,A,rect] = imcrop(...)举例 I = imread('ic.tif');I2 = imcrop(I,[60 40 100 90]);imshow(I)figure, imshow(I2) 相干命令: zoom 56.imfeature性能:计算图像区域的特色尺寸。语法: stats = imfeature(L,measurements) stats = imfeature(L,measurements,n) 举例 BW = imread('text.tif');L = bwlabel(BW);stats = imfeature(L,'all'); stats(23)ans =Area: 89Centroid: [95.6742 192.9775]BoundingBox: [87.5000 184.5000 16 15]MajorAxisLength: 19.9127MinorAxisLength: 14.2953Eccentricity: 0.6961Orientation: 9.0845 ConvexHull: [28x2 double]ConvexImage: [15x16 uint8 ] ConvexArea: 205Image: [15x16 uint8 ] FilledImage: [15x16 uint8 ] FilledArea: 122EulerNumber: 0 Extrema: [ 8x2 double] EquivDiameter: 10.6451Solidity: 0.4341Extent: 0.3708 PixelList: [89x2 double]相干命令:bwlabel ...

March 15, 2023 · 2 min · jiezi

关于图像处理:Matlab常用图像处理命令108例四

文章和代码以及样例图片等相干资源,曾经归档至【Github仓库:digital-image-processing-matlab】或者公众号【AIShareLab】回复 数字图像处理 也可获取。37.fwind1性能:用一维窗口办法设计二维FIR 过滤器。语法: h = fwind1(Hd,win)h = fwind1(Hd,win1,win2) h = fwind1(f1,f2,Hd,...) 举例 [f1,f2] = freqspace(21,'meshgrid');Hd = ones(21);r = sqrt(f1.^2 + f2.^2); Hd((r<0.1)|(r>0.5)) = 0;colormap(jet(64)) mesh(f1,f2,Hd)相干命令: conv2, filter2, fsamp2, freqspace, ftrans2, fwind2 38.fwind2性能:用二维窗口办法设计二维FIR 过滤器。语法: h = fwind2(Hd,win)h = fwind2(f1,f2,Hd,win)举例 [f1,f2] = freqspace(21,'meshgrid'); Hd = ones(21);r = sqrt(f1.^2 + f2.^2); Hd((r<0.1)|(r>0.5)) = 0;colormap(jet(64)) mesh(f1,f2,Hd)相干命令: conv2, filter2, fsamp2, freqspace, ftrans2, fwind1 39.getimage性能:从坐标轴获得图像数据。语法: A = getimage(h) [x,y,A] = getimage(h)[...,A,flag] = getimage(h) [...] = getimage举例 ...

March 14, 2023 · 2 min · jiezi

关于图像处理:Matlab常用图像处理命令108例三

文章和代码以及样例图片等相干资源,曾经归档至【Github仓库:digital-image-processing-matlab】或者公众号【AIShareLab】回复 数字图像处理 也可获取。26.edge性能:辨认强度图像中的边界。 语法: BW = edge(I,'sobel')BW = edge(I,'sobel',thresh)BW = edge(I,'sobel',thresh,direction) [BW,thresh] = edge(I,'sobel',...)BW = edge(I,'prewitt')BW = edge(I,'prewitt',thresh)BW = edge(I,'prewitt',thresh,direction) [BW,thresh] = edge(I,'prewitt',...)BW = edge(I,'roberts')BW = edge(I,'roberts',thresh) [BW,thresh] = edge(I,'roberts',...) BW = edge(I,'log')BW = edge(I,'log',thresh)BW = edge(I,'log',thresh,sigma) [BW,threshold] = edge(I,'log',...) BW = edge(I,'zerocross',thresh,h) [BW,thresh] = edge(I,'zerocross',...) BW = edge(I,'canny')BW = edge(I,'canny',thresh)BW = edge(I,'canny',thresh,sigma) [BW,threshold] = edge(I,'canny',...) 举例 I = imread('rice.tif');BW1 = edge(I,'prewitt'); BW2 = edge(I,'canny'); imshow(BW1);figure, imshow(BW2) 27.erode性能:弱化二进制图像的边界。 语法: ...

March 13, 2023 · 2 min · jiezi

关于图像处理:Matlab常用图像处理命令108例二

文章和代码以及样例图片等相干资源,曾经归档至【Github仓库:digital-image-processing-matlab】或者公众号【AIShareLab】回复 数字图像处理 也可获取。11.bwselect性能:在二进制图像中选择对象。语法: BW2 = bwselect(BW1,c,r,n) BW2 = bwselect(BW1,n) [BW2,idx] = bwselect(...) 举例 BW1 = imread('text.tif');c = [16 90 144];r = [85 197 247];BW2 = bwselect(BW1,c,r,4);imshow(BW1)figure, imshow(BW2) 相干命令: bwfill, bwlabel, impixel, roipoly, roifill 12.cmpermute性能:调整色彩映像表中的色彩。 语法: [Y,newmap] = cmpermute(X,map) [Y,newmap] = cmpermute(X,map,index)举例 To order a colormap by luminance, use:ntsc = rgb2ntsc(map);[dum,index] = sort(ntsc(:,1));[Y,newmap] = cmpermute(X,map,index);相干命令: randperm 13.cmunique性能:查找色彩映像表中特定的色彩及相应的图像。语法: [Y,newmap] = cmunique(X,map) [Y,newmap] = cmunique(RGB) [Y,newmap] = cmunique(I)相干命令: gray2ind, rgb2ind 14.col2im性能:将矩阵的列从新组织到块中。语法: A = col2im(B,[m n],[mm nn],block_type)A = col2im(B,[m n],[mm nn])相干命令: blkproc, colfilt, im2col, nlfilter ...

March 12, 2023 · 2 min · jiezi

关于图像处理:数字图像处理Matlab函数全汇总

文章和代码以及样例图片等相干资源,曾经归档至【Github仓库:digital-image-processing-matlab】或者公众号【AIShareLab】回复 数字图像处理 也可获取。图像显示colorbar 显示彩条 getimage 由坐标轴失去图像数据 ice(DIPUM) 交互黑白编辑 image 创立和显示图像对象 imagesc 缩放数据并显示为图像 immovie 由多帧图像制作电影 imshow 显示图像 imview 在Image Viewer中显示图像 montage 将多个图像帧显示为矩阵蒙太奇 movie 播放录制的电影帧 rgbcube 显示一个黑白RGB立方体 subimage 在单个图形中显示多幅图像 truesize 调整图像的显示尺寸 warp 将图像显示为纹理映射的外表 图像文件输出/输入Dicominfo 从一条DICOM音讯中读取元数据 Dicomread 读一幅DICOM图像 Dicomwrite 写一幅DICOM图像 Dicom-dict.txt 蕴含DICOM数据字典的文本文件 Dicomuid 产生DICOM惟一的识别器 Imfinfo 返回对于图像的文件的信息 Imread 读图像文件 Imwrite 写图像文件 图像算术Imabsdiff 计算两幅图像的相对差 Imadd 两幅图像相加或把常数加到图像上 Imcomplement 图像求补 Imdivide 两幅图像相除,或用常数除图像 Imlincomb 计算图像的线性组合 Immultiply 两幅图像相乘或用常数乘图像 Imsubtract 两幅图像相减,或从图像中减去常数 几何变换Checkerboard 创立棋盘格图像 Findbounds 求几何变换的输入范畴 Fliptform 颠倒TFORM构造的输出/输入 Imcrop 修剪图像 ...

March 10, 2023 · 3 min · jiezi

关于图像处理:matlab实现形态学图像处理

文章和代码以及样例图片等相干资源,曾经归档至【Github仓库:digital-image-processing-matlab】或者公众号【AIShareLab】回复 数字图像处理 也可获取。目标收缩的简略利用、应用 strel 函数、侵蚀的阐明函数imopen 和imclose 的利用、应用IPT函数bwhitmiss灰度图像形态学开运算和闭运算灰度图像形态学应用重构删除简单图像的背景内容收缩的简略利用A=imread('D:\pic\DIP3E_CH04\Fig0419(a)(text_gaps_of_1_and_2_pixels).tif');figure, imshow(A)B=[0 1 0;1 1 1;0 1 0];A2=imdilate(A,B);figure,imshow(A2)应用 strel 函数合成构造元素的阐明 se=strel('diamond',5)decomp=getsequence(se);whosdecomp(1)decomp(2)decomp(3)decomp(4)侵蚀的阐明 A=imread('D:\pic\DIP3E_CH09\Fig0905(a)(wirebond-mask).tif');figure, imshow(A)%原图像se=strel('disk',10)A2=imerode(A,se)figure, imshow(A2)%半径为10 的圆盘侵蚀后的图像se=strel('disk',5)A3=imerode(A,se)figure, imshow(A3)%半径为5 的圆盘侵蚀后的图像A4=imerode(A,strel('disk',20))figure, imshow(A4)%半径为20 的圆盘侵蚀后的图像函数imopen 和imclose 的利用f=imread('D:\pic\DIP3E_CH09\Fig0905(a)(wirebond-mask).tif');figure, imshow(f)%原图像se=strel('square',20);fo=imopen(f,se);figure, imshow(fo)%开运算后的图像fc=imclose(f,se);figure, imshow(fc)%闭运算后的图像foc=imclose(fo,se);figure, imshow(foc)%图像A2 经闭运算后的图像应用 IPT 函数bwhitmiss f=imread('D:\pic\DIP3E_CH09\FigP0918(left).tif')figure,imshow(f)B1=strel([0 0 0;0 1 1;0 1 0]);B2=strel([1 1 1;1 0 0;1 0 0]);g=bwhitmiss(f,B1,B2);figure,imshow(g)灰度图像形态学开运算和闭运算%%%%%%%%%应用开运算和闭运算做形态学平滑%%%%%%%%%%%%%%%%%clear allclcf=imread('D:\pic\DIP3E_CH09\Fig0941(a)(wood_dowels).tif');figure, imshow(f)%原图像se=strel('disk',5);fo=imopen(f,se);figure, imshow(fo)%开运算后的图像foc=imclose(fo,se);figure, imshow(foc)%图像A2 经闭运算后的图像fasf=f;for k=2:5 se=strel('disk',k); fasf=imclose(imopen(fasf,se),se);endfigure,imshow(fasf) %%%%%% 交替程序滤波后的图像%%%%%%%%%%应用顶帽变换%%%%%%%%%%%%%%clear allclcf=imread('D:\pic\DIP3E_CH09\Fig0940(a)(rice_image_with_intensity_gradient).tif');figure, imshow(f)%原图像se=strel('disk',10);fo=imopen(f,se);figure, imshow(fo)%经开运算解决后的图像f2=imsubtract(f,fo);figure, imshow(f2)f2=imtophat(f,se);figure, imshow(f2)se=strel('disk',3);g=imsubtract(imadd(f,imtophat(f,se)),imbothat(f,se));%低帽、顶帽figure, imshow(g)%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%颗粒剖析%%%%%%%%%%%%%%clear allclcf=imread('D:\pic\DIP3E_CH09\Fig0940(a)(rice_image_with_intensity_gradient).tif');sumpixels=zeros(1,36);for k=0:35 se=strel('disk',k); fo=imopen(f,se); sumpixels(k+1)=sum(fo(:));endfigure,plot(0:35,sumpixels);xlabel('k');ylabel('surface area')figure, plot(-diff(sumpixels))xlabel('k');ylabel('surface area reduction')%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%灰度图像形态学应用重构删除简单图像的背景%灰度图像形态学应用重构删除简单图像的背景clear allclcf=imread('D:\pic\DIP3E_CH09\Fig0944(a)(calculator).tif');figure, imshow(f)%原图像f_obr=imreconstruct(imerode(f,ones(1,71)),f);figure, imshow(f_obr)f_o=imopen(f,ones(1,71));%for comparisonfigure, imshow(f_o)f_thr=imsubtract(f,f_obr);figure, imshow(f_thr)f_th=imsubtract(f,f_o);%or imtophat(f,ones(1,71))figure, imshow(f_th)g_obr=imreconstruct(imerode(f_thr,ones(1,11)),f_thr);figure, imshow(g_obr)g_obrd=imdilate(g_obr,ones(1,21));figure, imshow(g_obrd)f2=imreconstruct(min(g_obrd,f_thr),f_thr);figure, imshow(f2)参考文献: ...

March 8, 2023 · 1 min · jiezi

关于图像处理:Matlab实现图像压缩

文章和代码以及样例图片等相干资源,曾经归档至【Github仓库:digital-image-processing-matlab】或者公众号【AIShareLab】回复 数字图像处理 也可获取。目标1. 了解图像压缩的相干概念及图像压缩的次要准则和目标;2. 把握霍夫曼编码3. 把握几种常见的图像压缩编码方法4. 利用 MATLAB 程序进行图像压缩 原理图像压缩原理图像压缩次要目标是为了节俭存储空间,减少传输速度。图像压缩的现实规范是信息失落起码,压缩比例最大。不损失图像品质的压缩称为无损压缩,无损压缩不可能达到很高的压缩比;损失图像品质的压缩称为有损压缩,高的压缩比是以就义图像品质为代价的。压缩的实现办法是对图像从新进行编码,心愿用更少的数据表示图像。 信息的冗余量有许多种,如空间冗余,工夫冗余,构造冗余,常识冗余,视觉冗余等,数据压缩本质上是缩小这些冗余量。高效编码的次要办法是尽可能去除图像中的冗余成分,从而以最小的码元蕴含最大的图像信息。 编码压缩办法有许多种,从不同的角度登程有不同的分类办法,从信息论角度登程可分为两大类。 (1)冗余度压缩办法,也称无损压缩、信息放弃编码或嫡编码。具体说就是解码图像和压缩编码前的图像严格雷同,没有失真,从数学上讲是一种可逆运算。 (2)信息量压缩办法,也称有损压缩、失真度编码或烟压缩编码。也就是说解码图像和原始图像是有差异的,容许有肯定的失真。 利用在多媒体中的图像压缩编码方法,从压缩编码算法原理上能够分为以下 3 类: (1)无损压缩编码品种哈夫曼(Huffman)编码,算术编码,行程(RLE)编码,Lempel zev 编码。 (2)有损压缩编码品种 预测编码,DPCM,静止弥补频率域办法:正交变换编码(如DCT),子带编码;空间域办法:统计分块编码;模型办法:分形编码,模型基编码;基于重要性:滤波,子采样,比特调配,向量量化;(3)混合编码。 有 JBIG,H261,JPEG,MPEG 等技术标准。 离散余弦变换(DCT)图像压缩原理离散余弦变换 DCT 在图像压缩中具备宽泛的利用,它是JPEG、MPEG 等数据压缩规范的重要数学根底。 和雷同图像品质的其余罕用文件格式(如GIF(可替换的图像文件格式),TIFF(标签图像文件格式),PCX(图形文件格式))相比,JPEG 是目前动态图像中压缩比最高的。JPEG 比其余几种压缩比要高得多,而图像品质都差不多(JPEG 解决的图像只有真彩图和灰度图)。正是因为其高压缩比,使得JPEG 被宽泛地利用于多媒体和网络程序中。JPEG 有几种模式,其中最罕用的是基于DCT 变换的程序型模式,又称为根本零碎(Baseline)。 用DCT 压缩图像的过程为: (1)首先将输出图像合成为8×8 或16×16 的块,而后对每个子块进行二维DCT变换。(2)将变换后失去的量化的DCT 系数进行编码和传送,造成压缩后的图像格式。 用 DCT 解压的过程为: (1)对每个8×8 或16×16 块进行二维DCT 反变换。(2)将反变换的矩阵的块合成一个繁多的图像。 余弦变换具备把高度相干数据能量集中的趋势,DCT 变换后矩阵的能量集中在矩阵的左上角,右下的大多数的DCT 系数值十分靠近于0。对于通常的图像来说,舍弃这些靠近于0 的DCT 的系数值,并不会对重构图像的画面质量带来显著的降落。所以,利用DCT变换进行图像压缩能够节约大量的存储空间。压缩应该在最正当地近似原图像的状况下应用起码的系数。应用系数的多少也决定了压缩比的大小。 在压缩过程的第 2 步中,能够正当地舍弃一些系数,从而失去压缩的目标。在压缩过程的第2 步,还能够采纳RLE 和Huffman 编码来进一步压缩。 行程编码(RLE)原理例如如下这幅的二值图像, 如果采纳行程编码能够按如下格局保留 其中10 和8 示意图像的宽和高。在这个小例子中行程编码并没有起到压缩图像的作用。这是因为这个图的尺寸过小,当图像尺寸较大时行程编码还是不错的无损压缩办法。对于灰度图像和二值图像,用行程编码—般都有很高的压缩率。行程编码方法实现起来很容易,对于具备长反复值的串的压缩编码很无效,例如:对于有大面积的暗影或色彩雷同的图像,应用这种办法压缩成果很好。很多位图文件格局都采纳行程编码,如TIFF,PCX,GEM,BMP等。 步骤MATLAB 中的变长码映射clear allclcf2=uint8([2 3 4 2;3 2 4 4;2 2 1 2;1 1 2 2])whos('f2')c=huffman(hist(double(f2(:)),4))h1f2=c(f2(:))'whos('h1f2')%h2f2=char(h1f2)'h2f2=[1 0 1 0 0 1 1 0 0 0 0 1 1 0 1 1;...' ' 1 ' ' 1 1 ' ' 1 0 0 1 ' ' 0 ' ';...' ' 0 ' ' 1 0 ' ' 1 ' ' 1 ' ']whos('h2f2')h2f2=h2f2(:);h2f2(h2f2==' ')=[];whos('h2f2')h3f2=mat2huff(f2)whos('h3f2')hcode=h3f2.code;whos('hcode')dec2bin(double(hcode))%-----------------------------------------%function CODE=huffman(p)error(nargchk(1,1,nargin));if(ndims(p)~=2)|(min(size(p))>1)|~isreal(p)|~isnumeric(p) error('p must be a real numeric vector');endglobal CODECODE=cell(length(p),1);%init the global cell arrayif (length(p)>1) %when more than one symbol.... p=p/sum(p);%Normalize the input probabilities s=reduce(p);%Do Huffman source symbol reductions makecode(s,[]);%Recursively(递归) generate the codeelse CODE={'1'};%else, trivial(一般的) one symbol caseend;%---------------------------------------------------------%function s=reduce(p);s=cell(length(p),1);for i=1:length(p) s{i}=i;endwhile size(s)>2 [p,i]=sort(p);%sort the symbol probabilities p(2)=p(1)+p(2);%Merge the 2 lowest probabilities p(1)=[];% and prune(,剪除、删除) the lowest one s=s(i); s{2}={s{1},s{2}}; s(1)=[];end%------------------------------------------------------------%function makecode(sc,codeword)global CODEif isa(sc,'cell') makecode(sc{1},[codeword 0]); makecode(sc{2},[codeword 1]);else CODE{sc}=char('0'+codeword);End%-----------------------------------------------------------%function y=mat2huff(x)if ndims(x)~=2|~isreal(x)|(~isnumeric(x) & ~islogical(x)) error('x must be a 2-D real numeric or logical matrix');endy.size=uint32(size(x));x=round(double(x));xmin=min(x(:));xmax=max(x(:));pmin=double(int16(xmin));pmin=uint16(pmin+32768);%y.min=pmin;x=x(:)';h=histc(x,xmin:xmax);if max(h)>65535 h=65535*h/max(h);endh=uint16(h);y.hist=h;%code the input matrix and store the resultmap=huffman(double(h));hx=map(x(:)-xmin+1)hx = ['1' ' ' '1' '0' ' ' '1' '1' '0' ' ' ' '... '0' '1' '1' ' ' '1' '1']';%hx=char(hx);hx=hx(:)';hx(hx==' ')=[];ysize=ceil(length(hx)/16);hx16=repmat('0',1,ysize*16);hx16(1:length(hx))=hx;hx16=reshape(hx16,16,ysize);hx16=hx16' - '0';twos=pow2(15:-1:0);y.code=uint16(sum(hx16.*twos(ones(ysize,1),:),2))';%-----------------------------------------------------------------------%离散余弦变换(DCT)图像压缩在图像的变换和压缩中,经常用到离散余弦变换(DCT)。DCT 具备能使图像的最重要的信息集中在DCT 的几个系数上的性能。正是基于此,DCT 通常利用于图像的压缩。 ...

March 7, 2023 · 2 min · jiezi

关于图像处理:Matlab实现小波变换

文章和代码以及样例图片等相干资源,曾经归档至【Github仓库:digital-image-processing-matlab】或者公众号【AIShareLab】回复 数字图像处理 也可获取。目标Haar、尺度和小波函数;比拟函数wavefast 和函数wavedec2 的执行工夫;小波的方向性和边缘检测。步骤Haar、尺度和小波函数[Lo_D,Hi_D,Lo_R,Hi_R]=wfilters('haar')%Haar 变换的合成和重构滤波器的长度为2waveinfo('haar');[phi,psi,xval]=wavefun('haar',10);xaxis=zeros(size(xval));subplot(121);plot(xval,phi,'k',xval,xaxis,'--k');axis([0 1 -1.5 1.5]);axis square;title('haar scaling function');subplot(122);plot(xval,psi,'k',xval,xaxis,'--k');axis([0 1 -1.5 1.5]);axis square;title('haar wavelet function');应用haar 滤波器的一个简略FWTf=magic(4)%应用Haar 的单尺度小波变换[c1,s1]=wavedec2(f,1,'haar')[c2,s2]=wavedec2(f,2,'haar')比拟函数wavefast 和函数wavedec2 的执行工夫function [varargout]=wavefilter(wname,type)%Check the input and output argumentserror (nargchk(1,2,nargin));if (nargin==1&nargout~=4)|(nargin==2&nargout~=2) error('Invalid number of output arguments');endif nargin == 1 & ~ischar(wname) error('WNAME must be a string');endif nargin == 2 & ~ischar(type) error('TYPE must be a string');endswitch lower(wname) case {'haar','db1'} ld=[1 1]/sqrt(2); hd=[-1 1]/sqrt(2); lr=ld; hr=-hd; case 'db4' ld=[-1.059740178499728e-002 3.288301166698295e-002 ... 3.084138183598697e-002 -1.870348117188811e-001 ... -2.798376941698385e-002 6.308807679295904e-001 ... 7.14846575525415e-001 2.303778133088552e-001]; t=(0:7); hd=ld; hd(end:-1:1)=cos(pi*t).*ld; lr=ld; lr(end:-1:1)=ld; hr=cos(pi*t).*ld; case 'sym4' ld=[-7.576571478927333e-002 -2.963552764599851e-002 ... 4.976186676320155e-001 8.03738758059161e-001 ... 2.978577956052774e-001 -9.921954357684722e-002 ... -1.260396726203783e-002 3.222310060404270e-002]; t=(0:7); hd=ld; hd(end:-1:1)=cos(pi*t).*ld; lr=ld; lr(end:-1:1)=ld; hr=cos(pi*t).*ld; case 'bior6.8' ld=[0 1.908831736481291e-003 -1.914286129088767e-003 ... -1.699063986760234e-002 1.193456527972926e-002 ... 4.973490349094079e-002 -7.726317316720414e-002 ... -9.405920349573646e-002 4.207962846098268e-001 ... 8.259229974584023e-001 4.207962846098268e-001 ... -9.405920349573646e-002 -7.726317316720414e-002 ... 4.973490349094079e-002 1.193456527972926e-002 ... -1.699063986760234e-002 -1.914286129088767e-003 ... 1.908831736481291e-003]; hd=[0 0 0 1.442628250562444e-002 -1.446750489679015e-002 ... -7.872200106262882e-002 4.036797903033992e-002 ... 4.178491091502746e-001 -7.589077294536542e-002 ... 4.178491091502746e-001 4.036797903033992e-002 ... -7.872200106262882e-002 -1.446750489679015e-002 ... 1.442628250562444e-002 0 0 0 0]; t=(0:17); lr=cos(pi*(t+1)).*hd; hr=cos(pi*t).*ld; case 'jpep9.7' ld=[0 0.02674875741080976 -0.01686411844287495 ... -0.07822326652898785 0.266861184428732 ... 0.6029490182363579 0.266861184428732 ... -0.07822326652898785 -0.01686411844287495 ... 0.02674875741080976]; hd=[0 -0.09127176311424948 0.05754352622849957 ... 0.5912717631142470 -1.115087052456994 ... 0.5912717631142470 0.05754352622849957 ... -0.09127176311424948 0 0]; t=(0:9); lr=cos(pi*(t+1)).*hd; hr=cos(pi*t).*ld; otherwise error('Unrecognizable wavelet name (WNAME).');end%Output the requested filtersif(nargin == 1) varargout(1:4)={ld,hd,lr,hr};else switch lower(type(1)) case 'd' varargout={ld,hd}; case 'r' varargout={lr,hr}; otherwise error('Unrecognizable filter TYPE.') endendfunction [c,s]=wavefast(x,n,varargin)error(nargchk(3,4,nargin));if nargin == 3 if ischar(varargin{1}) [lp,hp]=wavefilter(varargin{1},'d'); else error('Missing wavelet name'); endelse lp=varargin{1};hp=varargin{2};endf1=length(lp);sx=size(x);if (ndims(x)~=2)|(min(sx<2))|~isreal(x)|~isnumeric(x) error('X must be a real, numeric matrix');endif (ndims(lp)~=2)|~isreal(lp)|~isnumeric(lp) ... |(ndims(hp)~=2)|~isreal(hp)|~isnumeric(hp) ... |(f1~=length(hp)) | rem(f1,2)~=0 error(['LP and HP must be even and equal length real ,'...'numeric filter vectors']);endif ~isreal(n)|~isnumeric(n)|(n<1)|(n>log2(max(sx))) error(['N must be a real scalar between 1 and' ...'log2(max(size(x)))']);endc=[];s=sx;app=double(x);%for each decomposition...for i=1:n [app,keep]=symextend(app,f1); rows=symconv(app,hp,'row',f1,keep); coefs=symconv(rows,hp,'col',f1,keep); c=[coefs(:)' c]; s=[size(coefs);s]; coefs=symconv(rows,lp,'col',f1,keep); c=[coefs(:)' c]; rows=symconv(app,lp,'row',f1,keep); coefs=symconv(rows,hp,'col',f1,keep); c=[coefs(:)' c]; app=symconv(rows,lp,'col',f1,keep);endc=[app(:)' c];s=[size(app);s];function [y,keep]=symextend(x,f1)keep=floor((f1+size(x)-1)/2);y=padarray(x,[(f1-1) (f1-1)],'symmetric','both');function [ratio, maxdiff]=fwtcompare(f,n,wname)tic;[c1,s1]=wavedec2(f,n,wname);reftime=toc;tic;[c2,s2]=wavefast(f,n,wname);t2=toc;%compare the resultsratio=t2/(reftime+eps);maxdiff=abs(max(c1-c2)); function y=symconv(x,h,type,f1,keep)if strcmp(type,'row') y=conv2(x,h); y=y(:,1:2:end); y=y(:,f1/2+1:f1/2+keep(2));else y=conv2(x,h'); y=y(1:2:end,:); y=y(f1/2+1:f1/2+keep(1),:);end %比拟两种办法下的速度clear allclcf=imread('D:\图像库\DIP3E_CH07_Original_Images\Fig0701.tif','tif');[ratio,maxdifference]=fwtcompare(f,5,'db4')小波的方向性和边缘检测clear allclcf=imread('D:\图像库\DIP3E_CH07_Original_Images\Fig0701.tif');imshow(f);[c,s]=wavefast(f,1,'sym4');figure;wave2gray(c,s,-6);[nc,y]=wavecut('a',c,s);figure;wave2gray(nc,s,-6);edges=abs(waveback(nc,s,'sym4'));figure;imshow(mat2gray(edges));%子程序function w=wave2gray(c,s,scale,border)error(nargchk(2,4,nargin));if(ndims(c)~=2)|(size(c,1)~=1) error('c must be a row vector');endif(ndims(s)~=2)|~isreal(s)|~isnumeric(s)|(size(s,2)~=2) error('s must be a real,numeric two-column array');endelements=prod(s,2);if (length(c)<elements(end))|... ~(elements(1)+3*sum(elements(2:end-1))>=elements(end)) error(['[c s] must be a standard wavelet' ...'decomposition structure']);endif(nargin>2)&(~isreal(scale)|~isnumeric(scale)) error('scale must be a real,numeric scalar');endif(nargin>3)&(~ischar(border)) error('border must be character string');endif nargin==2 scale=1;%default scaleendif nargin<4 border='absord';%default borderendabsflag=scale<0;scale=abs(scale);if scale==0 scale=1;end[cd,w]=wavecut('a',c,s);w=mat2gray(w);cdx=max(abs(cd(:)))/scale;if absflag cd=mat2gray(abs(cd),[0,cdx]); fill=0;else cd=mat2gray(cd,[-cdx,cdx]); fill=0.5;end%build gray image one decomposition at a timefor i=size(s,1)-2:-1:1 ws=size(w); h=wavecopy('h',cd,s,i); pad=ws-size(h); frontporch=round(pad/2); h=padarray(h,frontporch,fill,'pre'); h=padarray(h,pad-frontporch,fill,'post'); v=wavecopy('v',cd,s,i); pad=ws-size(v); frontporch=round(pad/2); v=padarray(v,frontporch,fill,'pre'); h=padarray(v,pad-frontporch,fill,'post'); d=wavecopy('d',cd,s,i); pad=ws-size(d); frontporch=round(pad/2); d=padarray(d,frontporch,fill,'pre'); d=padarray(d,pad-frontporch,fill,'post'); %Add 1 pixel white border switch lower(border) case 'append' w=padarray(w,[1 1],1,'post'); h=padarray(h,[1 0],1,'post'); v=padarray(v,[0 1],1,'post'); case 'absord' w(:,end)=1; w(end,:)=1; h(end,:)=1; v(:,end)=1; otherwise error('Unrecognized border parameter'); end w=[w h;v d];endif nargout==0 imshow(w);%display resultendfunction [varargout]=waveback(c,s,varargin)error(nargchk(3,5,nargin));error(nargchk(1,2,nargout));if (ndims(c)~=2)|(size(c,1)~=1) error('c must be a row vector');endif(ndims(s)~=2)|~isreal(s)|~isnumeric(s)|(size(s,2)~=2) error('s must be a real,numeric two-column array');endelements=prod(s,2);if (length(c)<elements(end))|...~(elements(1)+3*sum(elements(2:end-1))>=elements(end)) error(['[c s] must be a standard wavelet' ... 'decomposition structure']);endnmax=size(s,1)-2;wname=varargin{1};filterchk=0;nchk=0;switch nargin case 3 if ischar(wname) [lp,hp]=wavefilter(wname,'r'); n=nmax; else error('updefined filter'); end if nargout~=1 error('wrong number of output arguments'); end case 4 if ischar(wname) [lp,hp]=wavefilter(wname,'r'); n=varargin{2}; nchk=1; else lp=varargin{1}; hp=varargin{2}; filterchk=1; n=nmax; if nargout~=1 error('wrong number of output arguments'); end endcase 5 lp=varargin{1}; hp=varargin{2}; filterchk=1; n=varargin{3}; nchk=1; otherwise error('improper number fo input arguments');endf1=length(lp);if filterchk if (ndims(lp)~=2)|~isreal(lp)|~isnumeric(lp) ... |(ndims(hp)~=2)|~isreal(hp)|~isnumeric(hp) ... |(f1~=length(hp)) | rem(f1,2)~=0 error(['LP and HP must be even and equal length real ,'... 'numeric filter vectors']); endendif nchk & (~isnumeric(n)|~isreal(n)) error('n must be a real numeric');endif (n>nmax)|(n<1) error('Invalid number (N) of reconstructions requested');endif (n~=nmax) & (nargout~=2) error('Not enough output arguments');endnc=c;ns=s;nnmax=nmax;for i=1:n a=symconvup(wavecopy('a',nc,ns),lp,lp,f1,ns(3,:))+ ... symconvup(wavecopy('h',nc,ns,nnmax),hp,lp,f1,ns(3,:))+ ... symconvup(wavecopy('v',nc,ns,nnmax),lp,hp,f1,ns(3,:))+ ... symconvup(wavecopy('d',nc,ns,nnmax),hp,hp,f1,ns(3,:)); nc=nc(4*prod(ns(1,:))+1:end); nc=[a(:)' nc]; ns=ns(3:end,:); ns=[ns(1,:);ns]; nnmax=size(ns,1)-2;endif nargout==1; a=nc; nc=repmat(0,ns(1,:)); nc(:)=a;endvarargout{1}=nc;if nargout==2 varargout{2}=ns;endfunction z=symconvup(x,f1,f2,fln,keep)y=zeros([2 1].*size(x));y(1:2:end,:)=x;y=conv2(y,f1');z=zeros([1 2].*size(y));z(:,1:2:end)=y;z=conv2(z,f2);z=z(fln-1:fln+keep(1)-2,fln-1:fln+keep(2)-2);function [nc,y]=wavecut(type,c,s,n)error(nargchk(3,4,nargin));if nargin==4 [nc,y]=wavework('cut',type,c,s,n);else [nc,y]=wavework('cut',type,c,s);Endfunction y=wavecopy(type,c,s,n)error(nargchk(3,4,nargin));if nargin==4 [nc,y]=wavework('cut',type,c,s,n);else [nc,y]=wavework('cut',type,c,s);Endfunction y=wavepaste(type,c,s,n)error(nargchk(5,5,nargin))nc=wavework('paste',type,c,s,n,x);function [varargout]=wavework(opcode,type,c,s,n,x)error(nargchk(4,6,nargin));if (ndims(c)~=2)|(size(c,1)~=1) error('c must be a row vector');endif(ndims(s)~=2)|~isreal(s)|~isnumeric(s)|(size(s,2)~=2) error('s must be a real,numeric two-column array');endelements=prod(s,2);if (length(c)<elements(end))|... ~(elements(1)+3*sum(elements(2:end-1))>=elements(end)) error(['[c s] must be a standard wavelet' ... 'decomposition structure']);endif strcmp (lower(opcode(1:3)),'pas') & nargin < 6 error('Not enough input arguments');endif nargin<5 n=1;endnmax=size(s,1)-2;aflag=(lower(type(1))=='a');if ~aflag & (n>nmax) error('N exceeds the decompositon in [c,s]');endswitch lower(type(1)) case 'a' nindex=1; start=1; stop=elements(1); ntst=nmax; case {'h','v','d'} switch type case 'h' offset=0; case 'v' offset=1; case 'd' offset=2; end nindex=size(s,1)-n; start=elements(1)+3*sum(elements(2:nmax-n+1))+ ... offset*elements(nindex)-1; stop=start+elements(nindex)-1; ntst=n; otherwise error('Type must begin with "a","h","v",or "d"');endswitch lower(opcode) case {'copy','cut'} y=repmat(0,s(nindex,:)); y(:)=c(start:stop); nc=c; if strcmp(lower(opcode(1:3)),'cut') nc(start:stop)=0; varargout={nc,y}; else varargout={y}; end case 'paste' if prod(size(x))~=elements(end-ntst) error('x is not sized for the requested paste'); else nc=c; nc(start:stop)=x(:); varargout={nc}; end otherwise error('unrecognized OPCODE');end参考文献: ...

March 6, 2023 · 4 min · jiezi

关于图像处理:Matlab实现彩色图像的转换-平滑-锐化与分割

文章和代码以及样例图片等相干资源,曾经归档至【Github仓库:digital-image-processing-matlab】或者公众号【AIShareLab】回复 数字图像处理 也可获取。目标应用 RGB、索引和灰度级图像间转换的函数把握彩色图像平滑的MATLAB 仿真彩色图像锐化RGB 彩色图像宰割内容1.应用 RGB、索引和灰度级图像间转换的函数 clcf=imread('D:\pic\DIP3E_CH06\Fig0651(a)(flower_no_compression).tif');imshow(f)title('原图像');[X1,map1]=rgb2ind(f,8,'nodither');figureimshow(X1,map1);%无抖动解决的色彩数缩小到8 的图像title('无抖动解决的色彩数缩小到8 的图像');[X2,map2]=rgb2ind(f,8,'dither');figureimshow(X2,map2)%有抖动解决的色彩数缩小到8 的图像title('有抖动解决的色彩数缩小到8 的图像');g=rgb2gray(f);g1=dither(g);figure,imshow(g);title('应用函数rgb2gray 失去的原图像的灰度级图像');figure,imshow(g1);title('经抖动解决后的灰度图像(这是一幅二值图像)');2.把握彩色图像平滑的MATLAB 仿真 function hsi = rgb2hsi(rgb)rgb=im2double(rgb);r=rgb(:,:,1);g=rgb(:,:,2);b=rgb(:,:,3);num=0.5*((r-g)+(r-b));den=sqrt((r-g).^2+(r-b).*(g-b));theta=acos(num./(den+eps));H=theta;H(b>g)=2*pi-H(b>g);H=H/(2*pi);num=min(min(r,g),b);den=r+g+b;den(den==0)=eps;S=1-3.*num./den;H(S==0)=0;I=(r+g+b)/3;hsi=cat(3,H,S,I);function rgb=hsi2rgb(hsi)H=hsi(:,:,1)*2*pi;S=hsi(:,:,2);I=hsi(:,:,3);R=zeros(size(hsi,1),size(hsi,2));G=zeros(size(hsi,1),size(hsi,2));B=zeros(size(hsi,1),size(hsi,2));idx=find((0<=H)&(H<2*pi/3));B(idx)=I(idx).*(1-S(idx));R(idx)=I(idx).*(1-S(idx).*cos(H(idx))./cos(pi/3-H(idx)));G(idx)=3*I(idx)-(R(idx)+B(idx));idx=find((2*pi/3<=H)&(H<4*pi/3));R(idx)=I(idx).*(1-S(idx));G(idx)=I(idx).*(1+S(idx).*cos(H(idx)-2*pi/3)./cos(pi-H(idx)));B(idx)=3*I(idx)-(R(idx)+G(idx));idx=find((4*pi/3<=H)&(H<=2*pi));G(idx)=I(idx).*(1-S(idx));B(idx)=I(idx).*(1+S(idx).*cos(H(idx)-4*pi/3)./cos(5*pi/3-H(idx)));R(idx)=3*I(idx)-(G(idx)+B(idx));rgb=cat(3,R,G,B);rgb=max(min(rgb,1),0);%%%%%%%%%%%主函数——图像平滑clear allclcfc=imread('D:\pic\DIP3E_CH06\Fig0637(a)(caster_stand_original).tif');imshow(fc)h=rgb2hsi(fc);H=h(:,:,1);%显示h 重量图像figure,imshow(H)title('H 重量')S=h(:,:,2);title('S 重量')figure,imshow(S)I=h(:,:,3);figure,imshow(I)title('I 重量')w=fspecial('average',25);I_filtered=imfilter(I,w,'replicate');h=cat(3,H,S,I_filtered);f=hsi2rgb(h);figure,imshow(f)f=min(f,1);%RGB images must have values in the range[0,1]figure,imshow(f)3.彩色图像锐化 clear allclcfc=imread('D:\pic\DIP3E_CH06\Fig0637(a)(caster_stand_original).tif');imshow(fc)lapmask=[1 1 1;1 -8 1;1 1 1];fen=imsubtract(fc,imfilter(fc,lapmask,'replicate'));figure,imshow(fen)4.RGB 彩色图像宰割 function [C,m]=covmatrix(X)[K,n]=size(X);X=double(X);if n==1 C=0; m=x;else m=sum(X,1)/K; X=X-m(ones(K,1),:); C=(X'*X)/(K-1); m=m';endfunction I=colorseg(varargin)f=varargin{2};if(ndims(f)~=3)|(size(f,3)~=3) error('Input image must be RGB!');endM=size(f,1); N=size(f,2);[f,L]=imstack2vectors(f);f=double(f);I=zeros(M*N,1);T=varargin{3};m=varargin{4};m=m(:)';%make sure that m is a row vetorif length(varargin)==4 method='euclidean';elseif length(varargin)==5 method='mahalanobis';else error('wrong number of inputs!');endswitch method case 'euclidean' p=length(f); D=sqrt(sum(abs(f-repmat(m,p,1)).^2,2)); case 'mahalanobis' C=varargin{5}; D=mahalanobis(f,C,m); otherwise error('Unknown segmentation method!');endJ=find(D<=T);I(J)=1;I=reshape(I,M,N);function [X,R]=imstack2vectors(S,MASK)[M,N,n]=size(S);if nargin==1 MASK=true(M,N);else MASK=MASK~=0;end[I,J]=find(MASK);R=[I,J];Q=M*N;X=reshape(S,Q,n);MASK=reshape(MASK,Q,1);X=X(MASK,:);%%%%%%RGB 图像宰割主程序clear allclcf=imread('D:\pic\DIP3E_CH06\Fig0637(a)(caster_stand_original).tif');mask=roipoly(f);figure,imshow(mask)%mask 是一幅2 值图像(大小与f 雷同)red=immultiply(mask,f(:,:,1));figure,imshow(red)title('red 重量');green=immultiply(mask,f(:,:,2));figure,imshow(green)title('green 重量');blue=immultiply(mask,f(:,:,3));figure,imshow(blue)title('blue 重量');g=cat(3,red,green,blue);figure,imshow(g)%计算ROI 中的点的均值向量和协方差矩阵[M,N,K]=size(g);I=reshape(g,M*N,3);idx=find(mask);I=double(I(idx,1:3));[C,m]=covmatrix(I);d=diag(C);sd=sqrt(d)'E25=colorseg('euclidean',f,25,m);%colorseg('m',f,T,m)T 值可取的值为25 的倍数时失去的不同后果参考文献: ...

March 5, 2023 · 1 min · jiezi

关于图像处理:图像的滤波与图像增强的Matlab实现

文章和代码以及样例图片等相干资源,曾经归档至【Github仓库:digital-image-processing-matlab】或者公众号【AIShareLab】回复 数字图像处理 也可获取。目标理解 MATLAB 工具箱中的滤波器。把握空间滤波学会对图像的空间变换内容A. 用滤波器祛除图象噪声在数字图像处理中,经常会遇到图像中混淆有许多的噪声。因而,在进行图像处理中,有时要先进行祛除噪声的工作。最罕用的祛除噪声的办法是用滤波器进行滤波解决。MATLAB 的图像处理工具箱里也设计了许多的滤波器。如均值滤波器、中值滤波器、维纳滤波器等。 (别离用均值滤波,中值滤波,及维纳滤波器祛除退出高斯噪声的图象) I=imread('D:\pic\DIP3E_CH04\FigP0438(left).tif ');J=imnoise(I,'gaussian',0,0.002);%进行均值滤波h=fspecial('average',3);I2=uint8(round(filter2(h,I)));%进行中值滤波I3=medfilt2(J,[3,3]);%进行维纳滤波I4=wiener2(J,[3,3]); %进行一次维纳滤波I5=wiener2(I4,[3,3]);%进行二次维纳滤波subplot(2,3,1),imshow(I),title('原图象')subplot(2,3,2),imshow(J),title('加噪声图象')subplot(2,3,3),imshow(I2),title('均值滤波后图象')subplot(2,3,4),imshow(I3),title('中值滤波后图象')subplot(2,3,5),imshow(I4),title('维纳滤波后图象')subplot(2,3,6),imshow(I5),title('两次维纳滤波后图象')B. 空间噪声滤波器%用函数imnoise2 生成具备表5.1 中的CDF 的随机数function R=imnoise2(type,M,N,a,b)if nargin ==1 a=0;b=1; M=1;N=1;elseif nargin ==3 a=0;b=1;endswitch lower(type) case 'uniform' R=a+(b-a)*rand(M,N); case 'gaussian' R=a+b*randn(M,N); case 'salt & pepper' if nargin <=3 a=0.05;b=0.05; end if (a+b)>1; error('The sum Pa+Pb must not exceed 1.') end R(1:M, 1:N) = 0.5; X=rand(M,N); c=find(X<=a); R(c)=0; u=a+b; c=find(X>a & X<=u); R(c)=1; case 'rayleigh' R=a+(-b*log(1-rand(M,N))).^0.5; case 'exponential' if nargin <=3; a=1; end if a<=0 error('Parameter a must be positive for exponential type.') end k=-1/a; R=k*log(1-rand(M,N)); case 'erlang' if nargin<=3 a=2;b=5; end if (b~=round(b)|b<=0) error('Parameter b must be a positive integer for Erlang') end k=-1/a; R=zeros(M,N); for j=1:b R=R+k*log(1-rand(M,N)); end otherwise error('unknown distribution type.')endfunction image=changeclass(class,varargin)switch class case 'uint8' image=im2uint8(varargin{:}); case 'uint16' image=im2uint16(varargin{:}); case 'double' image=im2double(varargin{:}); otherwise error('Unsupported IPT data class.');end%%%%% spfilt 函数与表中列出的任何滤波器在空间域执行滤波。function f = spfilt(g,type,m,n,parameter)if nargin ==2 m=3;n=3;Q=1.5;d=2;elseif nargin == 5 Q=parameter;d=parameter;elseif nargin== 4 Q=1.5; d=2;else error ('wrong number of inputs');endswitch type case 'amean' w=fspecial('average',[m,n]); f=imfilter(g,w, 'replicate'); case 'gmean' f=gmean(g,m,n); case 'hmean' f=harmean(g,m,n); case 'chmean' %f=charmean(g,m,n,Q); f=charmean(g,m,n,Q); case 'median' f=medfilt2(g,[m n], 'symmetric'); case 'max' f=ordfilt2(g,m*n,ones(m,n),'symmetric'); case 'min' f=ordfilt2(g,1,ones(m,n), 'symmetric'); case 'midpoint' f1=ordfilt2(g,1,ones(m,n), 'symmetric'); f2=ordfilt2(g,m*n,ones(m,n), 'symmetric'); f=imlincomb(0.5,f1,0.5,f2); case 'atrimmed' if(d<0)|(d/2~=round(d/2)) error('d must be a nonnegative, even integer.') end f=alphatrim(g,m,n,d); otherwise error('Unknown filter type.')endfunction f=gmean(g,m,n)inclass =class (g);g=im2double(g);warning off;f=exp(imfilter(log(g),ones(m,n),'replicate')).^(1/m/n);warning on;f=changeclass(inclass, f);function f=harmean(g,m,n)inclass=class(g);g=im2double(g);f=m*n./imfilter(1./(g+eps),ones(m,n),'replicate');f=changeclass(inclass,f);function f=charmean(g,m,n,q)inclass=class(g);g=im2double(g);f= imfilter(g.^(q+1),ones(m,n),'replicate');f=f./ (imfilter(g.^q,ones(m,n),'replicate')+eps);f=changeclass(inclass,f);function f=alphatrim(g,m,n,d)inclass = class(g);g=im2double(g);f=imfilter(g,ones(m,n),'symmetric');for k=1:d/2 f=imsubtract(f,ordfilt2(g,k,ones(m,n),'symmetric'));endfor k=(m*n – (d/2)+1):m*n f=imsubtract(f,ordfilt2(g,k,ones(m,n),'symmetric'));endf=f/(m*n-d);f=changeclass(inclass,f);%应用函数spfiltclear allclcf=imread('D:\pic\DIP3E_CH04\FigP0438(left).tif');[M,N]=size(f);R=imnoise2('salt & pepper',M,N,0.1,0);%被概率只有0.1 的胡椒噪声污染c=find(R==0);gp=f;gp(c)=0;figure, imshow(gp);R=imnoise2('salt & pepper',M,N,0,0.1);c=find(R==1);gs=f;gs(c)=255;figure,imshow(gs)fp=spfilt(gp,'chmean',3,3,1.5);%应用Q 为正值的反和谐滤波器figure, imshow(gp);fs=spfilt(gs,'chmean',3,3,-1.5);figure, imshow(gs);fpmax=spfilt(gp,'max',3,3); %应用最大最小滤波器figure, imshow(gp);fsmin=spfilt(gs,'min',3,3);figure, imshow(gs);C.用滤波器祛除图象噪声%产生一个等角变换用于测试图像f=checkerboard(50);s=0.8;theta=pi/6;T=[s*cos(theta) s*sin(theta) 0; -s*sin(theta) s*cos(theta) 0; 0 0 1];tform=maketform('affine',T);g=imtransform(f,tform);figure, imshow(g);g2=imtransform(f,tform,'nearest');figure, imshow(g2);g3=imtransform(f,tform,'FillValue',0.5);figure, imshow(g3);T2=[1 0 0;0 1 0; 50 50 1];tform2=maketform('affine',T2);g4=imtransform(f,tform2);figure, imshow(g4);g5=imtransform(f,tform2,'XData',[1 400],'YData',[1400],'FillValue',0.5);figure, imshow(g5);参考文献: ...

March 4, 2023 · 2 min · jiezi

关于图像处理:MATLAB实现图像的傅立叶变换

文章和代码以及样例图片等相干资源,曾经归档至【Github仓库:digital-image-processing-matlab】或者公众号【AIShareLab】回复 数字图像处理 也可获取。目标1.把握二维 DFT 变换及其物理意义 2.把握二维 DFT 变换的MATLAB 程序 3.空域滤波与频域滤波 原理1.利用傅立叶变换进行图像处理傅里叶变换是线性系统剖析的一个无力工具,它可能定量地剖析诸如数字化零碎、采样点、电子放大器、卷积滤波器、乐音和显示点等的作用。通过试验造就这项技能,将有助于解决大多数图像处理问题。对任何想在工作中无效利用数字图像处理技术的人来说,把工夫用在学习和把握博里叶变换上是很有必要的。 2.傅立叶(Fourier)变换的定义对于二维信号,二维Fourier 变换定义为: $$F(u, v)=\int_{-\infty}^{\infty} \int_{-\infty}^{\infty} f(x, y) e^{-j 2 \pi (u x+vy)} d x d y$$ 逆变换: $$f(x, y)=\int_{-\infty}^{\infty} \int_{-\infty}^{\infty} F(u d, v) e^{j 2 \pi (u x+vy) } d u d v$$ 二维离散傅立叶变换为: $$F(u, v)=\sum_{x=0}^{M-1} \sum_{y=0}^{N-1} f(x, y) e^{-j 2 \pi\left(\frac{\mathrm{ux}}{\mathrm{M}}+\frac{v y}{N}\right)}$$ 逆变换: $$f(x, y)=\frac{1}{M N} \sum_{u=0}^{M-1} \sum_{v=0}^{N-1} F(u, v) e^{j 2 \pi\left(\frac{\mathrm{ux}}{M}+\frac{v y}{N}\right)}$$ 图像的傅立叶变换与一维信号的傅立叶变换变换一样,有疾速算法,具体参见参考书目,无关傅立叶变换的疾速算法的程序不难找到。实际上,当初有实现傅立叶变换的芯片,能够实时实现傅立叶变换。 利用MATLAB 实现数字图像的傅立叶变换A. ...

March 3, 2023 · 1 min · jiezi

关于图像处理:图像处理│一张自拍即可实现变老变年轻带你感受时光流逝之美

我的项目成果飞浆是一个由百度推出的深度学习开发平台,为开发者提供了高效、易用、灵便和全面的深度学习开发工具和服务。PaddleGAN是飞浆在图像生成和解决畛域的一个代表性我的项目,通过深度学习的技术和飞浆的反对,PaddleGAN能够实现多种惊人的图像处理成果,例如图像转换、人脸编辑、动态效果生成等等。其中内置了StyleGAN V2与FOM别离实现人脸属性编辑和人脸动画成果。这些技术和利用在很多畛域都有宽泛的利用,例如娱乐、广告、电影制作、虚拟现实等等。 环境搭建这里集体举荐应用 Anaconda 搭建本地环境,因为如果我的项目太多,前期十分不好治理另外举荐全局更换 pip 源:pip config set global.index-url https://mirror.baidu.com/pypi/simple如果未更换源的话,下载会超级慢,甚至下载失败,也能够通过 -i 长期设置源:pip install xxx -i https://mirror.baidu.com/pypi/simple# 创立环境conda create --name PaddleGAN python=3.6# 激活环境activate PaddleGAN# 装置依赖cmakepip install cmake -i https://mirror.baidu.com/pypi/simple# 装置依赖boost pip install boost -i https://mirror.baidu.com/pypi/simple# 装置依赖numpypip install numpy -i https://mirror.baidu.com/pypi/simple# 装置依赖dlibpip install dlib==19.8.1 -i https://mirror.baidu.com/pypi/simple 下载PaddleGANGAN 是一种深度学习模型,是近年来简单散布上无监督学习最具前景的办法之一在装置依赖的时候,因应用的环境是 python3.6,所以须要将 requirements.txt 文件中的 opencv-python 加上一个版本号opencv-python==4.3.0.38,不然默认装置最新版本的,而最新版本的无奈被下载胜利# 下载源码git clone https://gitee.com/PaddlePaddle/PaddleGAN# 进入我的项目目录cd PaddleGAN# 装置我的项目依赖,这里肯定要设置全局源pip install -r requirements.txt# 装置环境python setup.py develop 装置飞浆装置 CPU 版本,不容易出错,但速度会有点慢,如果有 GPU 尽量应用 GPU 版本我这里只装置最新的,如果想要装置指定版本,请查看飞浆官网教程# CPU版本pip install paddlepaddle# GPU版本pip install paddlepaddle-gpu 生成图片潜码须要通过命令生成原图对应的 Latent Codeinput_image: 输出的图像门路output_path: 生成图片寄存的门路weight_paht: 预训练模型门路model_type: PaddleGAN 内置模型类型,若输出 PaddleGAN 已存在的模型类型,weight_paht 将生效,以后可用:ffhq-inversion,ffhq-toonifyseed: 随机数种子size: 模型参数,输入图片的分辨率style_dim: 模型参数,输入图片的分辨率n_mlp: 模型参数,格调z所输出的多层感知层的层数channel_multiplier: 模型参数,通道乘积,影响模型大小和生成图片的品质cpu: 是否应用 cpu 推理,若不应用,请在命令去除这里从网上找了一张我最喜爱的大甜甜照片来测试 ...

March 2, 2023 · 2 min · jiezi

关于图像处理:灰度直方图及直方图均衡化

文章和代码以及样例图片等相干资源,曾经归档至【Github仓库:digital-image-processing-matlab】或者公众号【AIShareLab】回复 数字图像处理 也可获取。一、试验目标1.直方图的显示 2.计算并绘制图像直方图 3.直方图的均衡化 二、试验内容灰度直方图用于显示图像的灰度值散布状况,是数字图像处理中最简略和最实用的工具。 MATLAB中提供了专门绘制直方图的函数 imhist() 。 1.直方图的显示imshow('D:\pic\DIP3E_CH02\Fig0221(a)(ctskull-256).tif');title('原图像')% 显示原图像A=imread('D:\pic\DIP3E_CH02\Fig0221(a)(ctskull-256).tif ','tif');figure;imhist(A);title('对应直方图')2.计算并绘制图像直方图A:用 bar 函数显示 A=imread('D:\pic\DIP3E_CH02\Fig0221(a)(ctskull-256).tif ','tif');h=imhist(A);h1=h(1:10:256);horz=1:10:256;bar(horz,h1)% 用bar 函数显示axis([0 255 0 15000])% 设置程度轴和垂直轴的最大值和最小值set(gca,'xtick',0:50:255)set(gca,'xtick',0:2000:15000)B:用 stem 函数显示 A=imread('D:\pic\DIP3E_CH02\Fig0221(a)(ctskull-256).tif ','tif');h=imhist(A);h1=h(1:10:256);horz=1:10:256;stem(horz,h1,'fill')% 用stem 函数显示axis([0 255 0 15000])% 设置程度轴和垂直轴的最大值和最小值set(gca,'xtick',[0:50:255])set(gca,'xtick',[0:2000:15000])C:用 plot 函数显示 A=imread('D:\pic\DIP3E_CH02\Fig0221(a)(ctskull-256).tif ','tif');h=imhist(A);plot(h)axis([0 255 0 15000])% 设置程度轴和垂直轴的最大值和最小值set(gca,'xtick',[0:50:255])set(gca,'xtick',[0:2000:15000])3.直方图均衡化imshow('D:\pic\DIP3E_CH02\Fig0221(a)(ctskull-256).tif');title('原图像')I=imread('D:\pic\DIP3E_CH02\Fig0221(a)(ctskull-256).tif ','tif');figure;imhist(I),title('对应直方图')% 从失去的直方图能够看出,图像的对比度很低,灰度级集中在70-160 范畴内,如果只取% 这个范畴内的灰度,并扩大到[0,255],则会明显增强图像对比度J=imadjust(I,[70/255 160/255],[]);figure;imshow(J),title('经灰度级调整后的图')figure;imhist(J),title('灰度级调整后的直方图')% MATLAB 还提供了histeq 函数(主动直方图均衡化)K=histeq(I);figure;imshow(K),title('经直方图均衡化后的图')figure;imhist(K),title('直方图均衡化后的直方图')

March 2, 2023 · 1 min · jiezi

关于图像处理:论文笔记二关于一些图像处理效果的评价指标

一.评估指标的分类对于图像品质的评估指标 个别依据是否参考原始影像分为三种:全参考 局部参考 无参考(1)全参考这些个别跟深度学习搭边构造相似性SSIM、峰值信噪比PSNR(这俩都是越大越好) 均方误差MSE(越小越好)等等 (2)局部参考没咋钻研过 (3)无参考这些比较简单 传统图像处理均值,标准差,均匀梯度,信息熵等等 二 论文用到的评估指标我的试验数据集是本人在谷歌卫星影像上收集的 六大洲每个州选一个国家 数据集一共100多幅图(是比深度学习的数据集外面图片少) 我从中抉择了六幅蕴含不同地物的影像 先放一组比照试验a是原图 b是咱们的后果 (参考影像选的上半局部色块) 咱们从上面几个方面做评估 (1)色块提取准确率评估这个就不说了 波及二值图标签的制作 (2)影像整体色调一致性评估分成五个块 统计每个块的均值 标准差 制成柱状图①分块办法:上下左右四个块 加两头雷同大小的块②柱状图: (3)影像部分地物色调一致性评估简略点说 一幅影像外面的地物 比如说路线 绿地之类的 雷同环境下 这些地物的特色应该类似①抉择的评估指标包含:因为是须要比拟 部分地物的相似性 属于全参考评估指标选了:梯度幅值类似偏差GMSD、色彩偏差c_st和扭曲水平D_st具体定义大家本人百度下,这里只阐明下指标的判断根据: 当梯度幅值类似偏差GMSD的值越小时,表明两个色块中抉择的样本区域间构造越类似,部分品质进化越小,地物特色越靠近。 色彩偏差c_st越小,阐明区域间地物均值差别越小,具备相近的特色。 扭曲水平反映出不同色块间雷同地物特色的差别大小,值越小,阐明地物差别越小,信息保真度较好。②而后抉择了这三个小区域 局部数据:** (4)影像整体品质评估这个是探讨影像通过解决当前 品质产生了怎么的变动的 次要抉择了 信息熵E、均匀梯度G 、空间频率SF和灰度方差乘积SMD2这四类影像品质评估指标这属于 无参考评估指标了 单纯思考后果影像 信息熵越大,图像携带的信息量越大,信息越丰盛。均匀梯度越大,图像档次越多,图像就越显得清晰。图像空间频率越高,图像越清晰。当图像越含糊时,整个图像的灰度较为平均,相邻像素之间的差值很小,即计算失去的SMD2后果越小;图像越清晰时,计算失去的SMD2后果会越大。我感觉我做的试验指标也太多了。。

February 23, 2023 · 1 min · jiezi

关于图像处理:图像分割单阈值大津法

一.图像宰割1.什么是图像宰割图像宰割就是把图像分成若干个特定的、具备独特性质的区域并提出感兴趣指标的技术和过程。也就是说图像宰割将图像细分为一个个子区域或物体,细分的水平取决于要解决的的问题,当咱们失去感兴趣区域时,宰割就进行。PS 打个岔:图像分类是什么 计算机看图像是一堆数字矩阵,不像咱们人眼这么高级 能分辨出外面比方有小狗 兔子这些货色。所以为了让计算机了解图像的内容,咱们须要利用图像分类,应用计算机视觉和机器学习算法解决图像,这个操作能够简略的为一张图像调配一个标签,如猫还是狗,或者也能够高级到解释图像的 内容并且返回一个可读的句子。 总的来说图像分类个别是波及计算机视觉和机器学习,相对来说更高级 比图像宰割波及范畴更广小结:图像宰割是取得想要的区域或者物体 图像分类是对图像中的内容进行了解和解释 2.现有图像宰割办法的分类少数宰割办法是基于灰度值的两个根本性质 不连续性和相似性(1)基于阈值的办法包含全局阈值、自适应阈值等等①全局阈值是指整幅图像应用同一个阈值做宰割解决,实用于背景和前景有显著比照的图像。依据整幅图像确定,然而这种办法只思考像素自身的灰度值,个别不思考空间特色,因此对噪声很敏感。罕用的全局阈值选取办法有利用图像灰度直方图的峰谷法、最小误差法、最大类间方差法、最大熵主动阈值法以及其它一些办法。②自适应阈值 在图像中比较复杂的状况下,全局阈值很难精确地将物体与背景离开。这时能够依据须要理论依照将图像分成若干子区域别离计算阈值,进行图像宰割,这时的阈值为自适应阈值。 举例子:cv2.threshold(src,thresh,maxval,type)cv2.adaptiveThreshold() (2)基于区域基于区域的办法是以间接寻找区域为根底的宰割技术①区域成长②区域决裂与聚合 今天独自写一篇 (3)基于边缘基于边缘的宰割办法 是以灰度部分激烈变化检测为根底 其中 线和边缘 是次要钻研对象边缘或者说边缘线段是连贯边缘像素的汇合 线两侧的灰度一侧远亮于该线上的灰度 另一侧是远暗于该线上的灰度边缘检测 (很多算子)先天独自写一篇 (4)基于特定实践特定实践大略有:聚类分析、模糊集实践、基因编码、小波变换等。小波变换用的也挺多的 这篇排到大后天了 二.单阈值大津法大津法属于全局阈值办法中的一种,即是最大类间方差法 大津法作为图像宰割中阈值选取的罕用算法,计算简略,不受图像亮度和对比度的影响,次要原理如下:影像的大小为M×N,将前景区域和背景区域的宰割阈值记作T,影像中像素值小于阈值T的像素个数记为N0,像素值大于阈值T的像素个数记为N1,则有: w0=N0/(M×N) w1=N1/(M×N) =w0×0+w1×1 g=w0×(0-)^2+w1×(1-)^2 其中w0为前景区域像素个数占整幅影像的比例,其像素均值为0;w1是背景区域像素个数占整幅影像的比例,其像素均值为1;为影像的总像素均值,g为类间方差,当计算出的类间方差g最大时,对应的阈值T即为最佳宰割成果的阈值。 #include <iostream>#include <opencv2/core.hpp>#include <opencv2/highgui.hpp>#include <opencv2/imgproc.hpp>#include <opencv2\imgproc\types_c.h>#include <opencv2/highgui/highgui_c.h>#include <opencv2/opencv.hpp>#include <iostream>using namespace std;using namespace cv;double Otsu(Mat& image){ int threshold = 0; double maxVariance = 0; double w0 = 0, w1 = 0;//前景与背景像素点所占比例 double u0 = 0, u1 = 0;//前景与背景像素值均匀灰度 int histogram[256] = { 0 }; //定义一个数组 长度为256 0-255 int Num = image.cols * image.rows; //总像素个数 //统计256个bin,每个bin像素的个数 for (int i = 0; i < image.rows; i++) { const uchar* p = image.ptr<uchar>(i); for (int j = 0; j < image.cols; j++) { histogram[int(*p++)]++; //cout<<"Histogram[data[i*image.step+j]]++:;"<<histogram[int(*p++)]++<<endl; } //*p++, *和++优先级是雷同的 先解援用取出指针指向的值, //而后再将指针地址加1,指向下一个地位。也就是取值为 *p 然而这时候指针曾经指向下一个地位 } //前景像素统计 for (int i = 1; i < 256; i++) { w0 = 0; //前景像素所占比例 w1 = 0; //背景像素所占比例 u0 = 0; //前景像素灰度均值 u1 = 0; //背景像素灰度均值 for (int j = 1; j <= i; j++) { w0 = w0 + histogram[j];//以i为阈值,统计前景像素比例 u0 = u0 + j * histogram[j];//以i为阈值,统计前景像素灰度总和 } u0 = u0 / w0; w0 = w0 / Num; //Num是总像素个数 //背景像素统计 for (int j = i + 1; j <= 255; j++) { w1 = w1 + histogram[j];//以i为阈值,统计前景像素个数 u1 = u1 + j * histogram[j];//以i为阈值,统计前景像素灰度总和 histogram[j]是像素值为j的像素个数 } u1 = u1 / w1; w1 = w1 / Num; // 后面的u1是总灰度和 除以w1总个数是前景的灰度均值// 后面的w1是总个数 除以Num当前才是比例 double variance = w0 * w1 * (u1 - u0) * (u1 - u0); //以后类间方差计算 if (variance > maxVariance) { maxVariance = variance; threshold = i; } } cout << "threshold:" << threshold << endl; return threshold;}int main(){ Mat img = imread("C://Users//马亚飞//Pictures//Saved Pictures//湖人.jpg"); imshow("原图", img); Mat img1; img.copyTo(img1); cvtColor(img, img, CV_BGR2GRAY); // 把img转为灰度图 cvtColor(img1, img1, CV_BGR2GRAY); //把img1转为灰度图 double th = Otsu(img); //调用Otsu函数 失去阈值th cout << "The return value of getOstu is: " << th << endl; //输入阈值th cout << "The return value of opencv threshold is: " << threshold(img1, img1, th, 255, CV_THRESH_OTSU);//opencv已实现的大津法 for (int i = 0; i < img.rows; i++) //行循环 { uchar* data = img.ptr<uchar>(i); //获取第i行的首地址 for (int j = 0; j < img.cols; j++) //列循环 { if (data[j] <= th) data[j] = 0; else data[j] = 255; } //行解决完结 } imshow("Ostu_img", img); //cv::namedWindow("Opencv_img", CV_WINDOW_NORMAL); cv::imshow("Opencv_img", img1); //对一次大津法 的彩色或者红色局部进行掩膜 //bitwise_not(img1, img1); //这里先变反转色彩 /*Mat src = imread("D://opencvdata//0//0.png"); src.setTo(0,img1); imshow("掩膜", src);*/ waitKey(0); return 0;}(威少的黑白图还有点像利拉德)都差不多 ...

February 19, 2023 · 2 min · jiezi

关于图像处理:红外图深度图彩色图转为原图raw

本地上传形式 <!DOCTYPE html><html lang="cn"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>客户端模仿</title> <link href="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"> <style> .bg-light { background-color: #f8f9fa!important; } .pt-3 { padding-top: 3rem!important; } .pb-3 { padding-bottom: 3rem!important; } a { text-decoration: none; } #canvas-dep { margin-left: -15px; } #canvas-inf { margin-left: -15px; } </style></head><body class="bg-light"> <canvas id="canvas-col" width="640" height="480"></canvas> <canvas id="canvas-dep" width="640" height="480"></canvas> <canvas id="canvas-inf" width="640" height="480"></canvas> <div class="container"> <div class="pt-3 pb-3 text-center"> <h2>图片查看工具</h2> <p class="lead">查看黑白、红外及深度原图</p> </div> <div class="row"> <div class="col-md-12 order-md-1"> <h4 class="mb-3">申请参数</h4> <form class="needs-validation" novalidate=""> <div class="row"> <div class="col-md-4 mb-3"> <label for="colfile">黑白</label> <input type="file" class="form-control" id="colfile" > <div class="invalid-feedback"> Valid appKey is required. </div> </div> <div class="col-md-4 mb-3"> <label for="depfile">深度图</label> <input type="file" class="form-control" id="depfile" > <div class="invalid-feedback"> Valid appKey is required. </div> </div> <div class="col-md-4 mb-3"> <label for="inffile">红外图</label> <input type="file" class="form-control" id="inffile" > <div class="invalid-feedback"> Valid appKey is required. </div> </div> </div> <hr class="mb-4"> <button class="btn btn-primary btn-lg btn-block" type="button" onclick="test();">测试</button> </form> </div> </div> </div> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <!-- <script src="https://cdn.bootcss.com/popper.js/1.14.7/umd/popper.min.js"></script> --> <script src="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script> <script type="text/javascript"> const w = 640; const h = 480; const depThresholdValue = 4000; const infThresholdValue = 1000; function test() { let colfile = $("#colfile"); if (colfile && colfile[0].files && colfile[0].files[0]) { console.log(colfile[0].files) let fileReader = new FileReader(); fileReader.onload = (event) => { var buffer = new Uint8Array(event.target.result); console.log(buffer) var ctx = document.getElementById("canvas-col").getContext('2d'); var data = ctx.createImageData(w, h); for(var index = 0; index < w * h; index ++) { let i = index * 4; let bi = index * 3; data.data[i] = buffer[bi]; data.data[i + 1] = buffer[bi + 1]; data.data[i + 2] = buffer[bi + 2]; data.data[i + 3] = 255; } ctx.putImageData(data, 0, 0); console.log('bye color'); } fileReader.readAsArrayBuffer(colfile[0].files[0]); } // let depfiles = $("#depfile"); if (depfiles && depfiles[0].files && depfiles[0].files[0]) { let fileReader = new FileReader(); fileReader.onload = (event) => { var buffer = new Uint8Array(event.target.result); var ctx = document.getElementById("canvas-dep").getContext('2d'); var data = ctx.createImageData(w, h); for(var index = 0; index < w * h; index ++) { let i = index * 4; let pixel = Math.ceil((buffer[index*2 + 1] * 256 + buffer[index*2]) * 255 / depThresholdValue); if (pixel > 255) pixel = 255; data.data[i] = pixel; data.data[i + 1] = pixel; data.data[i + 2] = pixel; data.data[i + 3] = 255; } ctx.putImageData(data, 0, 0); console.log('bye dep'); } fileReader.readAsArrayBuffer(depfiles[0].files[0]); } let inffiles = $("#inffile"); if (inffiles && inffiles[0].files && inffiles[0].files[0]) { let fileReader = new FileReader(); fileReader.onload = (event) => { var buffer = new Uint8Array(event.target.result); var ctx = document.getElementById("canvas-inf").getContext('2d'); var data = ctx.createImageData(w, h); for(var index = 0; index < w * h; index ++) { let i = index * 4; let pixel = Math.ceil((buffer[index*2 + 1] * 256 + buffer[index*2]) * 255 / infThresholdValue); if (pixel > 255) pixel = 255; data.data[i] = pixel; data.data[i + 1] = pixel; data.data[i + 2] = pixel; data.data[i + 3] = 255; } ctx.putImageData(data, 0, 0); console.log('bye inf'); } fileReader.readAsArrayBuffer(inffiles[0].files[0]); } } </script></body></html>ajax形式: ...

January 17, 2023 · 3 min · jiezi

关于图像处理:EfficientFormer-提升速度的同时保持性能使-ViT-在移动端成为可能

出品人:Towhee 技术团队 顾梦佳 因为大量的参数和其模型设计(注意力机制),基于 ViT 的模型通常比轻量级卷积网络慢几倍。因而,为实时应用程序部署 ViT 特地具备挑战性,尤其是在资源受限的硬件(如挪动设施)上。为了让 transformers 同时领有高性能和速度,EfficientFormer 从新扫视了 ViT 模型中应用的网络架构和运算符,引入一个维度统一的纯 Transformer 作为设计范例。 大量试验表明 EfficientFormer 系列模型在挪动设施上的性能和速度方面具备优越性。其中最快的模型 EfficientFormer-L1 在公开的图像数据集 ImageNet-1K 上实现了 79.2% 的 top-1 精度,在 iPhone 12 上的运行速度与 MobileNetV2×1.4 一样快。而最大的模型 EfficientFormer-L7 也可能以 7.0 毫秒的提早取得 83.3% 的准确率。EfficientFormer 证实正确设计的变压器能够使模型在放弃高性能的同时,在挪动设施上达到极低的提早。 Overview of EfficientFormer 基于提早剖析,EfficientFormer 的模型设计齐全基于 Transformers。该网络首先用一个卷积骨干用作 patch embedding,而后蕴含了一组 MetaBlock (MB)。其中 MB4D 和 MB3D 领有不同的 token mixer 配置,即以维度统一的形式排列的部分池化或全局多头自注意力。 相干材料: 代码地址:https://github.com/snap-resea...论文链接:EfficientFormer: Vision Transformers at MobileNet Speed更多材料:EfficientFormer:MobileNet 速度下的视觉Transformer

January 12, 2023 · 1 min · jiezi

关于图像处理:Mac图像处理软件Lightroom-Classic-2022

Lightroom Classic 2022是一款桌面照片编辑和管理软件,照片前期处理软件,数码摄影师必备工具,次要面向数码摄影师、图形设计等专业人士和高端用户,以及所有爱好拍照、须要拍照的人群,反对各种RAW图像相机配置,HDR全景照片,次要用于数码相片导入整顿、编辑解决、前期打印等制作。 应用Lightroom Classic ,您能够取得所需的所有桌面编辑工具,以便在照片中施展最佳性能。关上色彩,使黯淡的镜头充满活力,去除扩散注意力的物体,并拉直歪斜的镜头。 此外,最新版本提供了改良的性能,因而您能够比以往更快地工作。 Lightroom Classic 具备更好的性能,可让您导入照片,生成预览,并在创纪录的工夫内从Library挪动到Develop Module。应用范畴屏蔽工具能够依据色彩,亮度或深度轻松抉择要编辑的区域或对象。

August 13, 2022 · 1 min · jiezi

关于图像处理:ON1-Photo-RAW-20225-for-Macpslr滤镜raw图像编辑器

ON1 Photo RAW 2022 for Mac反对超过 800 多个摄像头,还反对 JPEG、TIF、PSD、PSB、PNG 和 DNG。这款专业级照片管理器、原始处理器、分层编辑器和成果应用程序蕴含您在一个摄影应用程序中所需的所有。 ON1 Photo RAW 2022.5 for Mac(ps/lr滤镜raw图像编辑器) ON1 Photo RAW 2022 for Mac软件特色天空调换人工智能延时摄影创作者Photoshop 插件主机无噪声集成导出和备份/目录组织摄影师须要导入、筛选和组织他们的照片库的所有原料加工以极致的图像清晰度、靓丽的色调,并放弃最轻微的细节合并照片应用带有内置过滤器的完满合成和遮罩工具人工智能驱动的性能和集成用于编辑肖像和缩小噪点的色彩和色调弱小的成果照片成果、滤镜、LUT 和预设的最佳汇合调整大小、打印、共享显示最高品质的照片云同步和挪动在您的所有设施和计算机上捕获、编辑、整顿和同步您的照片灵活性齐全领有它或抉择每月或每年订阅,订阅者始终无需额定费用即可取得软件的最新次要降级专业级工具业余的照片管理器、原始处理器、分层编辑器和成果应用程序弱小的掩蔽在应用程序的任何中央应用 Photo RAW 弱小的遮罩

August 7, 2022 · 1 min · jiezi

关于图像处理:Mac版Lightroom-Classic-2022激活文件

Lightroom Classic 2022是一款桌面照片编辑和管理软件,照片前期处理软件,数码摄影师必备工具,次要面向数码摄影师、图形设计等专业人士和高端用户,以及所有爱好拍照、须要拍照的人群,反对各种RAW图像相机配置,HDR全景照片,次要用于数码相片导入整顿、编辑解决、前期打印等制作。 装置LrC 2022中文版

August 2, 2022 · 1 min · jiezi

关于图像处理:JPEG公布智能图像编码提案结果火山引擎排名主观质量评测第一

近日,联结图像专家组JPEG颁布了JPEG AI规范平台提案后果,火山引擎多媒体实验室凭借软件平台BEE的优异体现,取得主观品质性能评比最佳问题。 JPEG是国际标准化组织、国际电工委员会和国际电信联盟的工作小组。信息“爆炸”时代,图像压缩对于互联网数据的传输和存储至关重要。得益于深度学习在图像压缩技术上的飞速停顿,JPEG AI小组公布了JPEG AI规范平台提案的征集,心愿构建全新的智能图像编码零碎,在晋升图片品质的同时,也能进步压缩性能。 来自世界各地的高校、科研院所、企业等数十家单位,提交了各自的软件平台计划。在雷同文件大小的前提下,图像压缩最重要的评估指标是人类的主观视觉感触。此次主观品质性能评比中,火山引擎软件平台BEE优于其余参赛软件平台,名列该项评比的榜首。 据悉,主动驾驶、媒体散发等场景对图像压缩技术有较高的要求,须要在无限带宽的条件下传输更多高质量图片。智能图像编码是人工智能技术在图像压缩上的跨畛域利用,在工业利用中具备微小后劲,是图像压缩的重要倒退方向。 火山引擎多媒体实验室负责人示意,BEE软件平台提出了多个翻新算法,解决了智能图像编码软硬件实现中的一系列难题,独创的“解耦式熵编码”技术更是化解了长期困扰端到端压缩的数据依赖,使得编解码速度有了根本性晋升。 据介绍,业界在智能图像编码过程中,熵编码与像素重建过程是高度耦合的,“这就如同一个力工和一个瓦工配合造房,力工每次给瓦工一块砖,等瓦工抹好水泥砌上并给出收条后,他才会去搬下一块。这在流程上造成了‘耦合’与‘依赖’,会影响造房效率。 ”火山引擎“解耦式熵编码”技术突破了这种制约,“力工不必再等瓦工抹水泥,只须要不停地搬砖放到指定地位就能够,甚至能够叫来更多力工一起搬。而瓦工也不必关注力工,只有指定地位有砖,他就能够不停地砌墙,从而大幅提高生产效率”。 图1:JPEG官网主观测试后果图,TEAM16、24为火山引擎的计划 图2:JPEG主观测试DMOS表,TEAM16、24为火山引擎的计划 测试结果表明,BEE平台的解码速度要比其余参赛软件平台高1-3个数量级,其速度曾经超过最新的规范H.266/VVC。在图形处理器GPU加持下,BEE平台解码工夫仅为H.266/VVC官网参考软件的一半。 火山引擎多媒体实验室是字节跳动旗下的钻研团队,致力于摸索多媒体畛域的前沿技术,参加国内、国内的标准化工作,其泛滥翻新算法曾经广泛应用在抖音、西瓜视频等产品的多媒体业务,并向火山引擎的企业级客户提供技术服务。

August 1, 2022 · 1 min · jiezi

关于图像处理:DxO-PureRAW帮你解决去马赛克去噪和镜头瑕疵校正等问题

DxO PureRAW是一款弱小的raw图像处理工具!DxO PureRAW采纳了智能技术,以解决影响所有RAW文件的七个问题:去马赛克,降噪,波纹,变形,色差,不想要的渐晕,以及不足清晰度,从而能够在Adobe Photoshop,Lightroom或其余程序中对其进行润色之前创立更好的RAW文件。 性能开释Adobe Photoshop和Lightroom的RAW文件编辑性能,这要归功于DxO独有的去马赛克,去噪和镜头缺点校对技术,从而能够在Adobe Photoshop,Lightroom或其余程序中对其进行润色之前创立更好的RAW文件。污浊,无瑕疵且无噪音的RAW照片DxO PureRAW的人工智能在保留细节与打消乐音之间达到了完满的均衡。DeepPRIME技术解决了您背后的这些问题,并且比您更好。您的镜头应该失去最好的校对。应用DxO专门设计的光学模块,能够主动校对设施中的缺点。复原旧的RAW文件从新开始编辑因为图像品质差,噪点或不足清晰度而搁置的旧照片。DxO PureRAW给您另一个机会。细节在于完满享受大幅面照片:DxO PureRAW揭示了您捕捉的每种纹理的所有细节和技巧,因而您能够享受令人难以置信的纯照片。柔和,无颗粒的散景永恒删除相机在照片的含糊区域中创立的“寄生”颗粒。DxO PureRAW为您的图像削减了令人难以置信的柔韧性。简化照片编辑操作只需单击几下即可应用DxO PureRAW,而后再应用惯例编辑软件,即可将RAW文件转换为DNG文件,而无需滑动器或进行简单的调整。 下载:https://www.macz.com/mac/8106...

July 28, 2022 · 1 min · jiezi

关于图像处理:图像处理解决方案-veImageX-技术演进之路

近日,第五届深度学习图像压缩挑战赛(以下将简称“ CLIC 大赛”)比赛结果颁布,首次参赛的火山引擎视频云多媒体实验室夺得视频压缩赛道第一名。压缩技术对于图像、视频利用非常重要。在保障同样的品质前提下,如何将图像压缩到更小的体积便于互联网信息传输,火山引擎视频云团队一直冲破压缩技术“天花板”。 以后字节跳动高峰期每秒需解决近百万张图片,基于今日头条、抖音等亿级 DAU 的实际打磨,与国内当先的压缩技术,火山引擎视频云打造图像一站式解决方案 veImageX ,笼罩上传、存储、解决、散发、展现、品质监控全链路,涵盖图像生产、图像生产、云平台三大利用场景。 图像生产图像生产场景次要将业务产生的图像写入图像存储中,起源包含用户端的图像上传、在镜像站或三方云的存储(按需拉取或全量迁徙)、在火山引擎的独立存储桶、业务自主合成的图片等。 图像生产图像生产环节提供了图片 URL 打包、图片实时处理链路、端数据上报等能力。 业务 URL 签发: 签发过程中会调用 veImageX 的签发服务,而后下发图片 URL 到业务客户端。通过签发的图片 URL ,携带了有效期和签名信息,能够无效避免 URL 盗链、 URL 篡改、域名盗用等。 客户端生产:业务图片加载 SDK ,实现图片下载、解码、展现、拜访数据上报一系列操作。客户端上报的数据,经数据上报核心荡涤后,会存储到数据仓库,供查问、监测图片的拜访性能、错误率等指标应用。 网络散发:在图片下载过程中,一般来说会首先拜访 CDN 。若 CDN 未缓存,则会触发回源,申请由源站接入层转发到图片静图服务。该服务次要负责拜访权限的校验、流量管制、图片资源下载以及动态图片的主体解决流程。申请处理过程中,对于须要利用图片算法、HEIF 静图 FPGA 编码的场景,图片静图服务会通过 RPC 申请 Lambda 计算平台,相应的能力已通过近程可调用函数的形式在平台上部署。对于 FPGA 不能反对的图片(分辨率过大或过小),会发送到 CPU 平台的 HEIF 静图编码服务做解决。对于动图转码解决的申请,图片静图服务会发送到动图服务做解决。因为动图的帧数有多有少,对于帧数多、分辨率高的大动图,当申请解决超过肯定工夫后,动图服务会将同步解决转为异步形式运行,并长期返回原图作为降级后果,待降级后果在 CDN 上的缓存生效后,相应的申请会再次回源,此时能够拿到异步解决后的图片。当图片静图服务实现图片申请的解决后,申请相应的数据会存入数据仓库,供数据分析、计费推量应用。 云平台veImageX 控制台作为一站式云平台,为用户提供了租户治理、配置下发、用量查问、品质监控、算法与算子治理等性能。 控制台的申请通过网关发往 veImageX 后端服务。 平台治理,相干的 OpenAPI 撑持了平台侧配置管理、用量查问、品质监控等能力。波及到后两者的场景,须要查问数据仓库获取对应的数据。波及到域名的场景,须要依赖 veImageX 的域名治理服务,和接入与散发的各个组件交互。 算子仓库,图像算法开发人员借此能够不便地治理、公布、运维图片算法模型。云数据迁徙服务则负责了图片生产场景中数据迁徙工作的治理。创意魔方服务实现了多图合成的能力,业务能够通过创意魔方附加组件创立款式,而后动静替换文字、图片,批量生产图片,实用于海报制作、商品图片合成等场景。 离线调用,作为图片实时散发链路的补充,这里还提供了图片算法的离线调用,蕴含了所有图片算法的 OpenAPI 。此外图片离线转码剖析平台能够应答批量图片的离线转码、画质剖析等场景。 veImageX 的技术演进历程veImageX 这些能力的造成并非欲速不达,而是随同着字节跳动的业务倒退一路成长。 ...

July 22, 2022 · 2 min · jiezi

关于图像处理:如何进行图像批量设计

Retrobatch mac版是一款图像批量设计工具,能够批改图片的大小尺寸、格局以及色彩,并且你还可能为这些图片批量加上本人的水印成果。这样就能够防止图片被其他人盗用了。灵便基于节点的批处理图像处理器意味着您能够将不同的操作混合,匹配和组合在一起,以实现完满的工作流程。超级充电每个操作的节点,从应用AppleScript将DPI更改为旋转到机器学习到自定义行为。优化您的图像,以便通过Internet疾速交付。批处理一个图像或数千个图像,反对读写通用文件格式,创立多个输出和多个输入。 下载:https://www.macz.com/mac/5953...

July 20, 2022 · 1 min · jiezi

关于图像处理:使用LRTimelapse延迟摄影工具帮你拍出精美大片

LRTimelapse是一款弱小的提早摄影工具,能够配合Adobe Camera RAW 和 Adobe After Effects、Adobe lightroom等程序来进行特效解决,次要是通过设置关键帧、均衡曝光、去除闪动等操作,再辅以渲染操作能够为你制作出延时摄影的成果。 性能特色动画和关键帧曝光,白平衡和其余任何Lightroom编辑工具。您能够应用Lightroom / ACR的全副后劲进行调色,甚至还能够制作突变,径向和油漆刷子过滤器让时间推移摄影的“圣杯” - (白天到黑夜的过渡)非常简单 - 只需在拍摄时手动调整相机或应用诸如qDslrDashboard之类的ra子机即可。只需点击一下Deflicker - 基于开发的图像的外观,而不用来到RAW工作流程。这给你最好的品质可能。与弱小的lrTExport插件无缝集成Lightroom CC Classic高性能的视频渲染引擎,可解决高达8K分辨率的高质量视频和MP4 / H.264,ProRes(甚至Windows),H.265和MJpeg。 下载:https://www.macz.com/mac/1289...

July 18, 2022 · 1 min · jiezi

关于图像处理:媲美ps的专业图像编辑工具Pixelmator-Pro

Pixelmator Pro 是一款能够和ps媲美的业余的图像编辑工具,可让您施展照片中的最佳成果,创立富丽的构图和设计,绘制,利用令人惊叹的成果,设计丑陋的文本,以及编辑图像任何你能设想的形式。Pixelmator 领有大量用于编辑和润饰照片,创立图形设计,绘画,绘制矢量图形以及增加令人惊叹的成果的工具。 软件下载:https://www.macz.com/mac/5180...

July 11, 2022 · 1 min · jiezi

关于图像处理:Lightroom-Classic-2022-1141版本更新Lightroom-Classic-2022新功能

近来,Lightroom Classic 2022 11.4.1版本更新!最新版Lightroom Classic 2022与旧版相比新增了许多新的性能,优化了细节。如:当初,您能够在Lightroom 应用编辑滑杆和「影片预设集」编辑影片。合并编辑工作流程,达成一致性美学!新版本减少新的「反转遮色片」选项可让您在群组和元件层级反转遮色片。您也能够抉择「复制并反转遮色片」。还有增强预设集的声援:应用「预设集总量滑杆」调整所套用预设集的强度。此外,也能够试试「最适化预设集」(可在 Lightroom 桌面版中应用),以将预设集疾速套用至相片中的天空和主体...

July 6, 2022 · 1 min · jiezi

关于图像处理:如何制作精美的图片

当咱们在日常浏览视频网站、查看公众号文章时,精美的图片封面往往更容易吸引咱们去点击。像咱们的技术类文章如果能在文中交叉一些有意思、简明扼要或有动感的图片,就看起来特地的有层次感。 一、什么样的图片适宜咱们反对CC0收费商用协定的图片,是没有版权危险的,当然咱们不是法律人士,但这是咱们在网上多番搜寻得出的共识! 二、图片素材起源目前网上得悉最靠谱的CC0协定图片库网站次要有Pixabay(pixabay.com)不过这个站点应用人数较多,简直没有其余同体量的cc0站点,所以有时关上比较慢,下面除了图片还有音视频、音效等资料 如何取得公众号文章的图片公众号文章的图片大都通过作者精美构思,或虚夸或低调都很吸引眼球,而这张图片往往不在注释中,无奈间接下载,通过浏览器关上,查看原文,搜寻cdn关键字能够找到,当然当初有很多现成的工具能够间接对源码进行正则匹配的提取,如微信公众号封面获取 - Toolzl工具 把文章的url粘过去即可。 三、图片加工解决图片的解决方法有很多,常见ps等牛刀,还有Online站点、手机app端,这里解说咱们罕用的解决工具 1)、人像抠图解决应用这个在线网站能够疾速抠图 上传图片 – remove.bg,产出PNG, 成果如下非付费用户只能下载低分辨率的小图,所以咱们可能须要用到上面这个工具,进行组合应用 2)、AI放大github上这个友人的工具,还是十分实用的 Releases · lltcggie/waifu2x-caffe (github.com) 咱们来试一下放大的成果,是不是很棒啊 3)、PPT叠图你没看错,PS咱们也不会,然鹅PPT来叠图、出图还是很容易做出精美图片,还能够当提词器、做提纲,十分的棒! 如本文的图片,其实就是个百度找来的背景图+红色长条形+绿色五边形的文字组合,创意来自网上学习~ 当然,图片是在ppt中用iSlide进行对立导出,所以十分不便,倡议iSlide官网下载安装一个,收费就够用了! 4)、制作gif动图工具有很多,都很玲珑,这里举荐用ScreenToGif,一个500K的小软件,设置好屏幕陆坪区域,而后用快捷键F7、F8进行开始和完结录制,再进行微调,可导出Gif、Avi等格局 写在最初好的工具、稳固的开发环境能够大幅提高工作效率,作者将本人日常积攒的教训分享进去心愿能帮忙更多的敌人! 码字不易,请多给点激励,【求评论、求点赞、求珍藏】

June 30, 2022 · 1 min · jiezi

关于图像处理:图像匹配大图中找小图之findtemplate源码解析

aircv是网易放出的小开源我的项目,应该也是当初做简略图像匹配被援用最多的我的项目了。上一篇做了如何应用aircv之find_template的形容,然而,它并不算是一个成熟的我的项目,外面的小坑不少,有待改良。明天先做个代码逻辑的解析。 外围函数find_template 与 find_all_templatefind_template函数是返回第一个最匹配的后果(地位未必在最下面),而find_all_template是返回所有大于指定置信度的后果。 比方要在思否页面截图中找后果如如下图所示: 咱们深刻进去看一下代码,就会发现find_template是这样写的: def find_template(im_source, im_search, threshold=0.5, rgb=False, bgremove=False): ''' @return find location if not found; return None ''' result = find_all_template(im_source, im_search, threshold, 1, rgb, bgremove) return result[0] if result else None好家伙! 间接调用find_all_template,而后取返回值的第一个。。。 所以find_all_template才是真正的外围,咱们排除掉无关代码,来看一下最要害的局部: def find_all_template(im_source, im_search, threshold=0.5, maxcnt=0, rgb=False, bgremove=False): # 匹配算法,aircv实际上在代码里写死了用CCOEFF_NORMED,大部分测试的成果,也的确是这个算法更好 method = cv2.TM_CCOEFF_NORMED # 获取匹配矩阵 res = cv2.matchTemplate(im_source, im_search, method) w, h = im_search.shape[1], im_search.shape[0] result = [] while True: # 找到匹配最大最小值 min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) top_left = max_loc if max_val < threshold: break # 计算中心点 middle_point = (top_left[0]+w/2, top_left[1]+h/2) # 计算四个角的点,存入后果集 result.append(dict( result=middle_point, rectangle=(top_left, (top_left[0], top_left[1] + h), (top_left[0] + w, top_left[1]), (top_left[0] + w, top_left[1] + h)), confidence=max_val )) # 把最匹配区域填充掉,再持续查找下一个 cv2.floodFill(res, None, max_loc, (-1000,), max_val-threshold+0.1, 1, flags=cv2.FLOODFILL_FIXED_RANGE) return result其中cv2.matchTemplate是opencv的办法,它的返回值是个矩阵,相当于用小图在大图上滑动,从左上角开始,每次挪动一个像素,而后计算一个匹配后果,最终造成后果矩阵。 ...

December 25, 2021 · 1 min · jiezi

关于图像处理:图像匹配大图中找小图最简单方法aircv之findtemplate

我的开源我的项目SimpleRPA外面,始终应用aircv的find_template办法来做图像匹配,最常见的场景就是从屏幕截图中,查找事后截好的小图,来确定下一步鼠标点击的地位: 比方在上面的钉钉PC端主页面中: 咱们来查找企业logo的地位: aircv是网易保护的一个小我的项目,外面有几个图像处理工具函数,它的装置很简略: pip install aircv其中被应用最多的,就是这个find_template办法,根本用法如下: import aircv as acmatch_result = ac.find_template(image_origin, image_template, threshold, bgremove)几个参数别离示意 image_origin:被查找的源图(下面实例中的钉钉主页面截图),要留神源图的宽和高,都必须大于或等于模板图image_template:要查找的模板小图(下面实例中的logo)threshold:最小置信度,在0到1之间。因为图像匹配并不需要每个像素准确统一,能够含糊匹配,所以这个值设定得越高,找到的区域就越靠近模板图,但设得太高就有可能找不到。bgremove:是否去除背景。如果这个值设置为True,那么函数外部会用Canny算子先提取图像轮廓,再做查找返回值match_result是个dict构造: match_result:{ 'result': (x,y), #tuple,示意辨认后果的中心点 'rectangle':[ #二位数组,示意辨认后果的矩形四个角 [left, top], [left, bottom], [right, top], [right, bottom] ], 'confidence': percentage #辨认后果的置信度,在0-1之间,越大越精准}这样咱们就能够用返回值在图片上标出矩形框的地位: import cv2rect = match_result['rectangle']cv2.rectangle(img_result, (rect[0][0], rect[0,1]), (rect[3][0], rect[3][1]), (0, 0, 220), 2) 这个find_template办法只返回一个最可信的后果,如果源图中有多个模板图,都想找回来那么须要find_all_template函数,参数齐全一样,只是返回值是个match_result数组。 然而这个库很久没有保护了,我给它提交了一个PR,也没人理,还是有一些坑的,当前再缓缓聊。

December 24, 2021 · 1 min · jiezi

关于图像处理:图像处理之灰度化

前言这两周实习须要应用python+opencv实现一个图像处理的程序,咱们组实现的是车牌辨认程序。借此机会略微理解一些图像处理的常识。 灰度化当咱们拿到一个照片后,首先进行灰度化解决将彩色照片变成灰色照片,因为一些办法只能解决灰色图像。将彩色图像变为灰色图像的过程称为灰度化。 灰度化,在RGB模型中,如果R=G=B时,则黑白示意一种灰度色彩,其中R=G=B的值叫灰度值,因而,灰度图像每个像素只需一个字节寄存灰度值(又称强度值、亮度值),灰度范畴为0-255。这让我想到了以前的黑白电视机,当初猜测以前只有黑白电视机的起因之一是传输速率没有那么高,应用灰度图像比彩色图像缩小3/2数据。假如一个像素点示意为f(x,y)=(r,g,b)那么变为灰色图像的的原理是f(x,y)=0.21r+0.71g+0.07+b成果如图 卷积在理解边缘检测之前,先理解卷积的概念假如取出边缘一圈0的两头是咱们灰度化后的图像,咱们先在外圈补一圈0,而后与咱们的3*3的卷积核(这是咱们本人定义的),顺次相乘求和,失去新的图像。如上图淡黄色里的每一个数值与对应地位黄色的每一个数值相乘而后求和。失去新的数值。而后咱们将淡黄色右移一格,失去邻近的数值,顺次失去新的图像。 边缘检测 边缘检测用于找到一个物体的边缘,咱们先察看一下一格物体的边缘有什么特点,如上图中人的肩膀,肩膀左下侧图像亮一些,肩膀外图像暗一些,肩膀轮廓左右图像灰度值变动较大。咱们找的边缘就是灰度值变动大的点。咱们在连续函数中求变动大的办法是导数。然而在离散的图像中求变化率用到了卷积。该办法蕴含两组3x3的矩阵,别离为横向及纵向,将之与图像作卷积,即可别离得出横向及纵向的亮度差分近似值。如果以A代表原始图像,Gx及Gy别离代表经横向及纵向边缘检测的图像,其公式如上。、成果如图

October 30, 2021 · 1 min · jiezi

关于图像处理:雾霾模糊图像增强教你如何去雾

摘要:具体介绍图像去雾算法,通过图像增强后的图像也能利用于指标检测、图像分类或物联网检测等畛域,并且成果更好。本文分享自华为云社区《图像预处理之图像去雾详解》,作者: eastmount。 一.图像去雾随着社会的倒退,环境污染逐步加剧,越来越多的城市频繁呈现雾霾,这不仅给人们的身体健康带来危害,还给那些依赖图像信息的计算机视觉零碎造成了不良影响,因为在雾天采集到的图像对比度和饱和度均较低,色彩易产生偏移与失真等。因而,寻找一种简略无效的图像去雾办法,对计算机视觉的后续钻研至关重要。 该局部次要从下列几篇论文摘取对图像去雾算法进行遍及,援用及参考中文论文: • 魏红伟, 等. 图像去雾算法钻研综述[J]. 软件导刊, 2021.• 王道累, 等. 图像去雾算法的综述及剖析[J]. 图学学报, 2021.• OpenCV图像增强万字详解(直方图均衡化、部分直方图均衡化、主动色调均衡化)- Eastmount 图像增强(Image Enhancement)是指依照某种特定的需要,突出图像中有用的信息,去除或者减弱无用的信息。图像增强的目标是使解决后的图像更适宜人眼的视觉个性或易于机器辨认。 在医学成像、遥感成像、人物摄影等畛域,图像增强技术都有着宽泛的利用。图像增强同时能够作为指标辨认、指标跟踪、特色点匹配、图像交融、超分辨率重构等图像处理算法的预处理算法。 近些年来,呈现了泛滥的单幅图像去雾算法,利用比拟宽泛的有: • 直方图均衡化去雾算法• Retinex去雾算法• 暗通道先验去雾算法• 基于卷积神经网络的DehazeNet去雾算法 其次要能够分为 3 类:基于图像增强的去雾算法、基于图像复原的去雾算法和基于 CNN 的去雾算法。 (1) 基于图像增强的去雾算法通过图像增强技术突出图像细节,晋升对比度,使之看起来更加清晰,这类算法的适用性较广。具体的算法有: • Retinex 算法依据成像原理,打消了反射重量的影响,达到了图像增强去雾的成果• 直方图均衡化算法使图像的像素散布更加平均,放大了图像的细节• 偏微分方程算法将图像视作一个偏微分方程,通过计算梯度场进步对比度• 小波变换算法对图像进行合成,放大有用的局部 此外,在这类算法的根底上呈现了泛滥的基于图像增强原理的改良算法。 (2) 基于图像复原的去雾算法次要是基于大气散射物理学模型,通过对大量有雾图像和无雾图像进行察看总结,失去其中存在的一些映射关系,而后依据有雾图像的造成过程来进行逆运算,从而复原清晰图像。其中最经典的要属何恺明大佬提出的: • 暗通道先验去雾算法通过对大量无雾图像进行特征分析,找到了无雾图像与大气散射模型中某些参数的先验关系。该算法复杂度低,去雾成果好,因而在其根底上呈现了大量基于暗通道先验的改良算法。 (3) 基于CNN的去雾算法应用 CNN 建设一个端到端的模型,通过有雾图像复原出无雾图像,目前应用神经网络进行去雾的算法次要有两种思路: 应用 CNN 生成大气散射模型的某些参数,而后再依据大气散射模型来复原无雾图像应用 CNN (例如 GAN)间接依据含糊图像生成无雾的清晰图像CNN 因其弱小的学习能力在多个畛域失去利用,因而也呈现了采纳 CNN 进行去雾的算法。2016年CAI等首次提出了一种名为DehazeNet的去雾网络,用于预计有雾图像的透射率。DehazeNet 将有雾的含糊图像作为输出,输入其透射率,基于大气散射模型实践复原出无雾的清晰图像。 下图是别离对直方图均衡化、暗通道先验去雾、DehazeNet和AOD-Net去雾算法进行测试,试验后果如图所示。由图可知,基于图像增强的直方图均衡化算法的去雾图像对比度明显增强,因为不思考降质起因,在减少对比度的同时也对噪声进行了放大,呈现细节失落与色调偏差景象。基于物理模型的暗通道去雾算法、基于神经网络的 DehazeNet 和 AOD-Net 算法的去雾成果较直方图均衡化算法更佳。 其余去雾算法比照后果如下图所示,比方城市和路线有无图像去雾成果比照。 最初,正如总结王道累老师总结的一样,目前针对有雾图像去雾的算法次要是从基于图像增强、图像复原和 CNN 3 个方向进行的。 • 基于图像增强的办法不思考有雾图像的造成过程,而是间接通过突出图像的细节,进步对比度等形式,从而使有雾图像看上去更加清晰。• 基于图像复原的办法则是追寻图像降质的物理过程,通过物理模型还原出清晰的图像。• 基于 CNN 的办法则是利用神经网络弱小的学习能力,寻找有雾图像与图像复原物理模型中某些系数的映射关系或者应用 GAN,依据有雾图像还原出无雾的清晰图像。 ...

October 13, 2021 · 4 min · jiezi

关于图像处理:数图春季授课作业一几何变换

工作:抉择典型图像(football.jpg)为钻研对象1.显示原图像2.将图像旋转45°并进行显示(不调用自带函数,利用矩阵变换) 原理:(原文链接:https://blog.csdn.net/Bryan_Q...) 以坐标原点为核心旋转的原理点p0绕坐标原点逆时针方向旋转角度失去点p1 $$ \begin{bmatrix} cos() & -sin & 0\\ sin & cos() & 0 \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x_0\\ y_0\\ 1 \end{bmatrix} = \begin{bmatrix} x_1\\ y_1\\ 1 \end{bmatrix}$$ 以任意图形中心点为坐标原点旋转原理(这合乎MATLAB的零碎空间坐标设置,绕核心旋转能够统一化几何变换问题,原点旋转解决具备个体化) 从上图可知,以任意图形核心为坐标原点旋转须要三步: (1)将坐标系I变成坐标系II注:坐标系I合乎MATLAB的零碎空间坐标设置,坐标系II中,图形核心是坐标原点。 $$ \begin{bmatrix} 1 & 0 & -0.5w\\ 0 & -1 & 0.5h \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} XI\\ YI\\ 1 \end{bmatrix} = \begin{bmatrix} XII\\ YII\\ 1 \end{bmatrix}$$ (2)将坐标系II旋转角 $$ \begin{bmatrix} cos() & -sin & 0\\ sin & cos() & 0 \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x_0\\ y_0\\ 1 \end{bmatrix} = \begin{bmatrix} x_1\\ y_1\\ 1 \end{bmatrix}$$ ...

April 3, 2021 · 2 min · jiezi

关于opencv:OpenCV萌新福音易上手的数字识别实践案例

摘要:信用卡辨认的案例用到了图像处理的一些基本操作,对刚上手CV的人来说还是比拟敌对的。本文分享自华为云社区《Python openCV案例:信用卡数字辨认》,原文作者:深蓝的回音 。 前言实际是测验真谛的唯一标准。 因为感觉一板一眼地学习OpenCV太过干燥,于是在网上找了一个以我的项目为导向的教程学习。话不多说,动手做起来。 一、案例介绍提供信用卡上的数字模板: 要求:辨认出信用卡上的数字,并将其间接打印在原图片上。尽管看起来很蠢,但既然能够将数字打印在图片上,阐明曾经胜利辨认数字,因而也能够将其转换为数字文本保留。车牌号辨认等我的项目的思路与此案例相似。 示例: 原图 解决后的图 二、步骤大抵分为如下几个步骤:1.模板读入2.模板预处理,将模板数字离开,并排序3.输出图像预处理,将图像中的数字局部提取进去4.将数字与模板数字进行匹配,匹配率最高的即为对应数字。 1、模板读入,以及一些包的导入,函数定义等import cv2 as cvimport numpy as npimport myutilsdef cv_show(name, img): # 自定义的展现函数 cv.imshow(name, img) cv.waitKey(0)# 读入模板图n = 'text'img = cv.imread("images/ocr_a_reference.png")# cv_show(n, template) # 自定义的展现函数,不便显示图片2、模板预处理,将模板数字离开,并排序 模板的预处理程序:灰度图,二值化,再进行轮廓检测。须要留神的是openCV检测轮廓时是检测红色边框,因而要将模板图的数字二值化变为红色。 # 模板转换为灰度图ref = cv.cvtColor(img, cv.COLOR_BGR2GRAY)# cv_show(n, ref)# 转换为二值图,把数字局部变为红色ref = cv.threshold(ref, 10, 255, cv.THRESH_BINARY_INV)[1] # 骚写法,函数多个返回值为元组,这里取第二个返回值cv_show(n, ref)# 对模板进行轮廓检测,失去轮廓信息refCnts, hierarchy = cv.findContours(ref.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)cv.drawContours(img, refCnts, -1, (0, 0, 255), 2) # 第一个参数为指标图像# cv_show(n, img) ...

March 16, 2021 · 3 min · jiezi

关于图像处理:图床SVG矢量图全都有六款图像处理类开源项目集合

明天 Gitee 为开发者们举荐的六款开源我的项目,蕴含了 Canvas 渲染引擎、图床、矢量图形渲染库、SVG生成工具、图片合成工具等,充沛满足开发者们在开发过程中的图像处理需要。话不多说,咱们间接往下看: 1.quark-renderer我的项目作者: quark-renderer 开源许可协定: BSD-3-Clause 我的项目地址:https://gitee.com/quark-renderer/quark-renderer 一款轻量且弱小的 Canvas(&SVG) 渲染引擎,从 ZRender 改良而来。 2.picbed我的项目作者: staugur 开源许可协定: BSD-3-Clause 我的项目地址:https://gitee.com/staugur/picbed 基于Flask的Web自建图床,反对存储到本地、又拍云、七牛云、阿里云OSS、腾讯云COS、GitHub、Gitee 等。 3.picasso2d我的项目作者: onecool 开源许可协定: BSD-3-Clause 我的项目地址:https://gitee.com/picasso2d/picasso2d Picasso 2D 是一款高质量的2D矢量图形渲染库。 它反对path,matrix,gradient,pattern,image和truetype字体。 4.SvgBadgeTool我的项目作者: Hamm 开源许可协定: MuLanPSL-2.0 我的项目地址:https://gitee.com/hamm/svg_badge_tool Svg Badge Tool是一个疾速生成SVG的小工具,反对传入参数进行生成svg的可外链小图标。 5.orly我的项目作者: 楠木 开源许可协定: MIT 我的项目地址:https://gitee.com/nanmu42/orly O'RLY 封面工厂是一个娱乐性的书籍封面生成器, 反对输出多种语言。 O'RLY 基于Golang和Vue.js实现。 6.image-combiner我的项目作者: opensourcechen 开源许可协定: MIT-996 我的项目地址:https://gitee.com/opensourcechen/image-combiner ImageCombiner是一个专门用于图片合成的工具,没有很简单的性能,简略实用,从理论业务场景登程,提供简略的接口,几行代码即可实现图片拼合(当然用于合成水印也能够),素材上反对图片和文本两种,反对定位、缩放、圆角、透明度、色彩、字体、字号、删除线、居中绘制、文本主动换行等个性,足够笼罩图片合成的日常需要。 点击前面的链接,去 Gitee 上看看更多的图像处理类开源我的项目:https://gitee.com/explore/image-processing

September 29, 2020 · 1 min · jiezi

关于图像处理:Python-给图片补边qbit

前言本文次要是为了给宽图片高低补边试验环境Windows 10 2004Python 3.8.3Pillow 7.1.2代码# encoding: utf-8# author: qbit# date: 2020-09-2# summary: 给宽图片高低补白边,让其满足肯定比例,而后缩放到指定尺寸import mathfrom PIL import Imagedef add_white_edge(inImgPath, outImgPath, width, height): r""" 给宽图片高低补白边,让其满足肯定比例,而后缩放到指定尺寸 inImgPath: 输出图片门路 outImgPath: 输入图片门路 width: 最终宽度 height: 最终高度 """ print(f'{inImgPath}') inImg: Image.Image = Image.open(inImgPath) bgWidth = inImg.width bgHeight = inImg.height if bgWidth > bgHeight: bgHeight = math.ceil((bgWidth * height) / width) # 创立一个红色背景图片 bgImg: Image.Image = Image.new("RGB", (bgWidth, bgHeight), (255, 255, 255)) bgImg.paste(inImg, (0, round((bgHeight - inImg.height) / 2))) bgImg.resize((width, height), Image.LANCZOS).save(outImgPath)if __name__ == "__main__": add_white_edge('wide.jpg', 'wide_out.jpg', 108, 150)示例输出图片样例(点击图片查看边框) ...

September 2, 2020 · 1 min · jiezi

关于图像处理:YUVyuv422yuv420pyuv420sp-convert-to-RGB

void convert_yuv420p_to_rgb_buffer(unsigned char* yuv, unsigned char* rgb, unsigned int width, unsigned int height) { int y, u, v; int r, g, b; unsigned char* rgbPixel = rgb; unsigned char* yuvPixel = yuv; unsigned char* uHeader = yuv + width * height; unsigned char* vHeader = yuv + width * height + (width * height) / 4; int half_width = width / 2; for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { y = *yuvPixel; yuvPixel++; u = *(uHeader + (i / 2 + (j / 2 * half_width))); v = *(vHeader + (i / 2 + (j / 2 * half_width))); // yuv to rgb, 整数、移位, 缩小计算量 r = y + ((360 * (v - 128)) >> 8); r = r > 255 ? 255 : (r < 0 ? 0 : r); *rgbPixel = r; rgbPixel++; g = y - (((88 * (u - 128) + 184 * (v - 128))) >> 8); g = g > 255 ? 255 : (g < 0 ? 0 : g); *rgbPixel = g; rgbPixel++; b = y + ((455 * (u - 128)) >> 8); b = b > 255 ? 255 : (b < 0 ? 0 : b); *rgbPixel = b; rgbPixel++; } } } void convert_yuv420sp_to_rgb_buffer(unsigned char* yuv, unsigned char* rgb, unsigned int width, unsigned int height) { int y, u, v; int r, g, b; unsigned char* rgbPixel = rgb; unsigned char* yuvPixel = yuv; unsigned char* uHeader = yuv + width * height; //unsigned char* vHeader = yuv + width * height + (width * height) / 4; int half_width = width / 2; for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { y = *yuvPixel; yuvPixel++; u = *(uHeader + (i / 2 + (j / 2 * half_width)) * 2); // 留神: 因为是整数乘除, 这里 (i / 2 * 2) 不肯定都等于 i, 不要简化。 v = *(uHeader + (i / 2 + (j / 2 * half_width)) * 2+1); // yuv to rgb, 整数、移位, 缩小计算量 r = y + ((360 * (v - 128)) >> 8); r = r > 255 ? 255 : (r < 0 ? 0 : r); *rgbPixel = r; rgbPixel++; g = y - (((88 * (u - 128) + 184 * (v - 128))) >> 8); g = g > 255 ? 255 : (g < 0 ? 0 : g); *rgbPixel = g; rgbPixel++; b = y + ((455 * (u - 128)) >> 8); b = b > 255 ? 255 : (b < 0 ? 0 : b); *rgbPixel = b; rgbPixel++; } } } void convert_yuyv_to_rgb_buffer(unsigned char* yuv, unsigned char* rgb, unsigned int width, unsigned int height) { unsigned int i; unsigned char* rgbPixel = rgb; unsigned char* yuvPixel = yuv; int y0, u, y1, v; int r, g, b; for (i = 0; i < width * height / 2; i++) { y0 = *yuvPixel; yuvPixel++; u = *yuvPixel; yuvPixel++; y1 = *yuvPixel; yuvPixel++; v = *yuvPixel; yuvPixel++; // yuv to rgb, 整数、移位, 缩小计算量 r = y0 + ((360 * (v - 128)) >> 8); r = r > 255 ? 255 : (r < 0 ? 0 : r); *rgbPixel = r; rgbPixel++; g = y0 - (((88 * (u - 128) + 184 * (v - 128))) >> 8); g = g > 255 ? 255 : (g < 0 ? 0 : g); *rgbPixel = g; rgbPixel++; b = y0 + ((455 * (u - 128)) >> 8); b = b > 255 ? 255 : (b < 0 ? 0 : b); *rgbPixel = b; rgbPixel++; // yuv to rgb, 整数、移位, 缩小计算量 r = y1 + ((360 * (v - 128)) >> 8); r = r > 255 ? 255 : (r < 0 ? 0 : r); *rgbPixel = r; rgbPixel++; g = y1 - (((88 * (u - 128) + 184 * (v - 128))) >> 8); g = g > 255 ? 255 : (g < 0 ? 0 : g); *rgbPixel = g; rgbPixel++; b = y1 + ((455 * (u - 128)) >> 8); b = b > 255 ? 255 : (b < 0 ? 0 : b); *rgbPixel = b; rgbPixel++; } }

August 13, 2020 · 4 min · jiezi

关于图像处理:YUVyuv422yuv420pyuv420sp-convert-to-RGB

void convert_yuv420p_to_rgb_buffer(unsigned char* yuv, unsigned char* rgb, unsigned int width, unsigned int height) { int y, u, v; int r, g, b; unsigned char* rgbPixel = rgb; unsigned char* yuvPixel = yuv; unsigned char* uHeader = yuv + width * height; unsigned char* vHeader = yuv + width * height + (width * height) / 4; int half_width = width / 2; for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { y = *yuvPixel; yuvPixel++; u = *(uHeader + (i / 2 + (j / 2 * half_width))); v = *(vHeader + (i / 2 + (j / 2 * half_width))); // yuv to rgb, 整数、移位, 缩小计算量 r = y + ((360 * (v - 128)) >> 8); r = r > 255 ? 255 : (r < 0 ? 0 : r); *rgbPixel = r; rgbPixel++; g = y - (((88 * (u - 128) + 184 * (v - 128))) >> 8); g = g > 255 ? 255 : (g < 0 ? 0 : g); *rgbPixel = g; rgbPixel++; b = y + ((455 * (u - 128)) >> 8); b = b > 255 ? 255 : (b < 0 ? 0 : b); *rgbPixel = b; rgbPixel++; } } } void convert_yuv420sp_to_rgb_buffer(unsigned char* yuv, unsigned char* rgb, unsigned int width, unsigned int height) { int y, u, v; int r, g, b; unsigned char* rgbPixel = rgb; unsigned char* yuvPixel = yuv; unsigned char* uHeader = yuv + width * height; //unsigned char* vHeader = yuv + width * height + (width * height) / 4; int half_width = width / 2; for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { y = *yuvPixel; yuvPixel++; u = *(uHeader + (i / 2 + (j / 2 * half_width)) * 2); // 留神: 因为是整数乘除, 这里 (i / 2 * 2) 不肯定都等于 i, 不要简化。 v = *(uHeader + (i / 2 + (j / 2 * half_width)) * 2+1); // yuv to rgb, 整数、移位, 缩小计算量 r = y + ((360 * (v - 128)) >> 8); r = r > 255 ? 255 : (r < 0 ? 0 : r); *rgbPixel = r; rgbPixel++; g = y - (((88 * (u - 128) + 184 * (v - 128))) >> 8); g = g > 255 ? 255 : (g < 0 ? 0 : g); *rgbPixel = g; rgbPixel++; b = y + ((455 * (u - 128)) >> 8); b = b > 255 ? 255 : (b < 0 ? 0 : b); *rgbPixel = b; rgbPixel++; } } } void convert_yuyv_to_rgb_buffer(unsigned char* yuv, unsigned char* rgb, unsigned int width, unsigned int height) { unsigned int i; unsigned char* rgbPixel = rgb; unsigned char* yuvPixel = yuv; int y0, u, y1, v; int r, g, b; for (i = 0; i < width * height / 2; i++) { y0 = *yuvPixel; yuvPixel++; u = *yuvPixel; yuvPixel++; y1 = *yuvPixel; yuvPixel++; v = *yuvPixel; yuvPixel++; // yuv to rgb, 整数、移位, 缩小计算量 r = y0 + ((360 * (v - 128)) >> 8); r = r > 255 ? 255 : (r < 0 ? 0 : r); *rgbPixel = r; rgbPixel++; g = y0 - (((88 * (u - 128) + 184 * (v - 128))) >> 8); g = g > 255 ? 255 : (g < 0 ? 0 : g); *rgbPixel = g; rgbPixel++; b = y0 + ((455 * (u - 128)) >> 8); b = b > 255 ? 255 : (b < 0 ? 0 : b); *rgbPixel = b; rgbPixel++; // yuv to rgb, 整数、移位, 缩小计算量 r = y1 + ((360 * (v - 128)) >> 8); r = r > 255 ? 255 : (r < 0 ? 0 : r); *rgbPixel = r; rgbPixel++; g = y1 - (((88 * (u - 128) + 184 * (v - 128))) >> 8); g = g > 255 ? 255 : (g < 0 ? 0 : g); *rgbPixel = g; rgbPixel++; b = y1 + ((455 * (u - 128)) >> 8); b = b > 255 ? 255 : (b < 0 ? 0 : b); *rgbPixel = b; rgbPixel++; } }

August 13, 2020 · 4 min · jiezi

Recompressor一款高质量免费的图像压缩工具

文章导读在日常工作中,我们经常会遇到图像文件过大的问题,这时候就需要对图像文件进行压缩处理。市面上也有很多优秀的压缩工具,但是难免会遇到压缩率低、压缩之后变模糊、收费等一些情况,下面分享的一款软件就很好的解决了这个问题。 软件介绍Recompressor是一个追求将图像进行最佳压缩的在线工具,压缩的全程中通过浏览器提供在线文件完整预览,在文件尺寸和质量之间取得完美平衡,该网站使用完全免费并且无广告,支持用户自定义压缩方式,超高颜值等等优秀的地方。总结一下,具有一下特点: 1.超高颜值 2.操作方便 3.自定义压缩方式 4.实时查看压缩率 5.纯免费 6.数据安全 7.处理速度快 网站地址网站地址 效果预览

June 20, 2020 · 1 min · jiezi

母亲节倒计时选礼物救急指南

选礼物是千古大难题之一,母亲节来临之际,借助机器学习、大数据分析、图像增强等 AI 技术,可以帮你为母亲送上一份走心的礼物。距离母亲节只剩两天了,你为母亲大人选好礼物了吗? 要让礼物达到美观、实用兼具且能讨母上大人喜欢,这实在是一个令人纠结的难题,对于平时置身代码海洋中的程序员来说更是令人头大。 置身代码海洋无法自拔的程序员 根据不靠谱情报,在母亲节来临之际,程序员表现各有不同: 第一种:什么?母亲节快到了? 第二种:奥,母亲节快到了,到时候给我妈打个电话吧,问问她想要啥礼物。 第三种:打开某电商 App,搜索「母亲节礼物」,从推荐列表的前三个里面选 1 个(一般是按摩工具之类)。 第四种:打开某电商 App,搜索「清洁工具套装」,然后买一套扫帚拖把鸡毛掸子寄给母上大人…… 「妈妈再打我一次」礼物套装 还有连电商 App 都没有的程序员,可能会直接选择最简单直接的方法:发红包。 所以,礼物到底该怎么选? 听说,AI 已经比你会选了。 选项一:用算法推荐中意的礼物有一款叫做「礼记」的小程序,利用大数据与机器学习,通过 5-6 个对送礼对象问题的回答,就能推荐出量身定制的礼物清单。 「礼记」的选礼问卷 经过亲测,推荐跟被赠送者喜好匹配度还不错,如果没有最中意的,也能通过推荐清单寻找灵感。 此外,欧莱雅也曾有过类似的尝试,在 2017 年推出了一款聊天机器人 Beauty Gifter,根据送礼者及收礼者的问答,推荐最合适的化妆品礼物。 这款机器人是欧莱雅与 Automat 的一个合作项目,Beauty Gifter 选礼物的方式,还是通过精心设计的问卷,寻找出最贴合的礼品。 被赠予者会收到卡片询问他们的护肤、美妆偏好等。如果担心破坏了惊喜,只要送礼物的一方对这些信息足够了解,也可以自己来回答卡片问卷。 选项二:送妈妈靓丽穿搭母亲节,也可以考虑送给妈妈一个穿搭助理。 在 2017 年 Facebook 年度开发者大会 F8 上,就有潮流和美妆服务机器人 Epytom Stylist 和 Sephora 现身。此后,亚马逊也推出了 Echo Look,这款机器人将图形识别功能和 Alexa 结合在一起,帮助人们挑选服装。 Echo Look 兼具图形识别与语音识别功能 Echo Look 有一个深度感应摄像头,和用于闪光灯的 LED 照明,以及计算机视觉等技术。它的工作原理是,穿好衣服后,通过声控,帮自己拍摄全身长的景深照片或者短视频,然后建立起用户的个人服装风格喜好数据集。 之后,它会利用机器学习算法,结合时尚专家的建议,评估用户的穿搭是否合适。 甚至对用户的穿搭颜色、风格与潮流提供指导建议。 ...

May 10, 2019 · 1 min · jiezi

阿里开源轻量级深度学习端侧推理引擎-MNN

阿里妹导读:近日,阿里正式开源轻量级深度学习端侧推理引擎“MNN”。AI科学家贾扬清如此评价道:“与 Tensorflow、Caffe2 等同时覆盖训练和推理的通用框架相比,MNN 更注重在推理时的加速和优化,解决在模型部署的阶段的效率问题,从而在移动端更高效地实现模型背后的业务。这和服务器端 TensorRT 等推理引擎的想法不谋而合。在大规模机器学习应用中,考虑到大规模的模型部署,机器学习的推理侧计算量往往是训练侧计算量的十倍以上,所以推理侧的优化尤其重要。” MNN背后的技术框架如何设计?未来有哪些规划?今天一起来深入了解。 1、MNN是什么? MNN 是一个轻量级的深度学习端侧推理引擎,核心解决深度神经网络模型在端侧推理运行问题,涵盖深度神经网络模型的优化、转换和推理。目前,MNN已经在手淘、手猫、优酷、聚划算、UC、飞猪、千牛等 20 多个 App 中使用,覆盖直播、短视频、搜索推荐、商品图像搜索、互动营销、权益发放、安全风控等场景,每天稳定运行上亿次。此外,菜鸟自提柜等 IoT 设备中也有应用。在 2018 年双十一购物节中,MNN 在天猫晚会笑脸红包、扫一扫、明星猜拳大战等场景中使用。 该项目已经在 Github 开源,关注“阿里技术”官方公众号,并在对话框内回复“MNN”,即可获得 Github 下载链接、了解更多详情。 2、MNN的优势MNN 负责加载网络模型,推理预测返回相关结果,整个推理过程可以分为模型的加载解析、计算图的调度、在异构后端上高效运行。MNN 具有通用性、轻量性、高性能、易用性的特征: 通用性: 支持 Tensorflow、Caffe、ONNX 等主流模型格式,支持 CNN、RNN、GAN 等常用网络;支持 86 个 TensorflowOp、34 个 CaffeOp ;各计算设备支持的 MNN Op 数:CPU 71 个,Metal 55 个,OpenCL 40 个,Vulkan 35 个;支持 iOS 8.0+、Android 4.3+ 和具有POSIX接口的嵌入式设备;支持异构设备混合计算,目前支持 CPU 和 GPU,可以动态导入 GPU Op 插件,替代 CPU Op 的实现;轻量性: 针对端侧设备特点深度定制和裁剪,无任何依赖,可以方便地部署到移动设备和各种嵌入式设备中;iOS 平台上,armv7+arm64 静态库大小 5MB 左右,链接生成可执行文件增加大小 620KB 左右,metallib 文件 600KB 左右;Android 平台上,so 大小 400KB 左右,OpenCL 库 400KB 左右,Vulkan 库 400KB 左右;高性能: ...

May 7, 2019 · 2 min · jiezi

GAN的一些很酷的应用

摘要: 本文主要讲述了生成对抗网络GANs的发展和主要应用。在GAN发展的最初几年里,我们取得了令人瞩目的进展。当然,现在不会是像恐怖电影里那样有邮票大小的面部照片了。2017年,Gan制作了1024×1024张能愚弄人才童子军的照片。在未来几年,我们可能会看到GAN生成的高质量视频,由此衍生的商业应用程序即将来临。作为GAN系列的一部分,我们研究了一些很酷的应用程序,希望它们能作你的GAN应用程序的灵感来源。创建动画角色众所周知,游戏开发和动画制作成本很高,并且雇佣了许多制作艺术家来完成相对常规的任务。但通过GAN就可以自动生成动画角色并为其上色。发生器和鉴别器由多层卷积层、批标准化和具有跳过链接的relu组成。姿势引导人形像生成通过姿势的附加输入,我们可以将图像转换为不同的姿势。例如,右上角图像是基础姿势,右下角是生成的图像。下面的优化结果列是生成的图像。该设计由二级图像发生器和鉴频器组成。生成器使用元数据(姿势)和原始图像重建图像。鉴别器使用原始图像作为CGAN设计标签输入的一部分。CycleGAN跨域名转让将很可能成为第一批商业应用。GANs将图像从一个领域(如真实的风景)转换为另一个领域(莫奈绘画或梵高)。例如,它可以在斑马和马之间转换图片。Cyclegan构建了两个网络G和F来构建从一个域到另一个域以及反向的图像。它使用鉴别器d来批评生成的图像有多好。例如,G将真实图像转换为梵高风格的绘画,并且DY用于区分图像是真实的还是生成的。域A到域B:我们在反向域B域A中重复该过程:PixelDTGAN根据名人图片推荐商品已经成为时尚博客和电子商务的热门话题。Pixeldtgan的作用就是从图像中创建服装图像和样式。超分辨率从低分辨率创建超分辨率图像。这是GAN显示出非常令人印象深刻的结果,也是具有直接商业可能性的一个领域。与许多GAN的设计类似,它是由多层卷积层、批标准化、高级relu和跳过连接组成。GAN的逐步发展Progressive GAN可能是第一个展示商业化图像质量的GAN之一。以下是由GAN创建的1024×1024名人形象。它采用分而治之的策略,使训练更加可行。卷积层的一次又一次训练构建出2倍分辨率的图像。在9个阶段中,生成1024×1024图像。高分辨率图像合成需要注意的是这并非图像分割,而是从语义图上生成图像。由于采集样本非常昂贵,我们采用生成的数据来补充培训数据集,以降低开发成本。在训练自动驾驶汽车时可以自动生成视频,而不是看到它们在附近巡航,这就为我们的生活带来了便捷。网络设计:文本到图像(StackGAN)文本到图像是域转移GAN的早期应用之一。比如,我们输入一个句子就可以生成多个符合描述的图像。文本到图像合成另一个比较通用的实现:人脸合成不同姿态下的合成面:使用单个输入图像,我们可以在不同的视角下创建面。例如,我们可以使用它来转换更容易进行人脸识别图像。图像修复几十年前,修复图像一直是一个重要的课题。gan就可以用于修复图像并用创建的“内容”填充缺失的部分。学习联合分配用面部字符P(金发,女性,微笑,戴眼镜),P(棕色,男性,微笑,没有眼镜)等不同组合创建GAN是很不现实的。维数的诅咒使得GAN的数量呈指数增长。但我们可以学习单个数据分布并将它们组合以形成不同的分布,即不同的属性组合。DiscoGANDiscoGAN提供了匹配的风格:许多潜在的应用程序。DiscoGAN在没有标签或配对的情况下学习跨域关系。例如,它成功地将样式(或图案)从一个域(手提包)传输到另一个域(鞋子)。DiscoGAN和cyclegan在网络设计中非常相似。Pix2PixPIX2PIx是一种图像到图像的翻译,在跨域Gan的论文中经常被引用。例如,它可以将卫星图像转换为地图(图片左下角)。DTN从图片中创建表情符号。纹理合成图像编辑 (IcGAN)重建或编辑具有特定属性的图像。人脸老化(Age-cGAN)神经照片编辑器基于内容的图像编辑:例如,扩展发带。细化图像目标检测这是用gan增强现有解决方案的一个应用程序。图像融合将图像混合在一起。视频生成创建新的视频序列。它识别出什么是背景,并为前台操作创建新的时间序列。视频链接生成三维对象这是用gan创建三维对象时经常引用的一篇文章。音乐的产生GaN可以应用于非图像领域,如作曲。医疗(异常检测)GAN还可以扩展到其他行业,例如医学中的肿瘤检测。进一步阅读本文展示了一些GAN的相关应用程序。如果你感兴趣想进一步研究GAN可以继续阅读以下文章:第一部分:重点介绍如何应用gans解决深层次学习问题,以及为什么培训gans如此困难。GAN-关于GAN的综合考察(上)第二部分:GAN培训问题解决概述。GAN-关于GAN的综合考察(下)本系列中的所有文章:GaN-GaN系列(从头到尾)本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 26, 2019 · 1 min · jiezi

[译] 解密 Mapbox 卫星影像处理神器 Robosat

英文原文地址:https://www.openstreetmap.org…英文原文作者:daniel前言最近,Mapbox 开源了端到端的卫星影像特征提取工具 RoboSat。下面我将以来自 OpenAerialMap 的 Tanzania 区域的无人机影像 演示如何在自定义图像数据集上运行完整的RoboSat流程。目标我们的目标是通过手把手的教学,在Dar es Salaam 和 Zanzibar 附近提取建筑物轮廓。我建议手工你过一遍 Zanzibar Mapping Initiative 和 OpenAerialMap 来建立对数据集的直观先验了解。整体步骤从无人机影像提取建筑轮廓包含下面几个步骤:数据准备:创建训练数据集训练模型:分割模型提取特征后处理:将分割结果转为简单的几何格式首先,带你创建一个基于 OpenAerialMap 的无人机影像并且带有 OpenStreetMap 建筑物轮廓蒙版的数据集。接着,我将演示如何训练 RoboSat 分割模型在新的无人机影像如何提取建筑。最后,我将介绍略好将预测结果转化为简单的多边形并映射到 OpenStreetMap 上。数据准备Zanzibar Mapping Initiative 通过OpenAerialMap提供他们的无人机影像。这是一个你可以手动浏览地图。训练RoboSat 的分割模型需要同时提供对应的 Slippy Map tiles 格式的无人机影像和对应的建筑物轮廓数据集。你可以认为这些由二进制组成的蒙版是用来标记建筑物对应区域是否存在建筑。让我们开始提取 Dar es Salaam 和 Zanzibar 边界框吧。从对应的无人机图像范围中提取OSM建筑物几何图形提取作为训练数据集,因此需要在 OSM 上截取对应的区域。我有个在 GeoFabrik 工作的朋友提供了方便又先进的 提取工具 osmium-tool ,它可以帮助实现上述任务。wget –limit-rate=1M http://download.geofabrik.de/africa/tanzania-latest.osm.pbfosmium extract –bbox ‘38.9410400390625,-7.0545565715284955,39.70458984374999,-5.711646879515092’ tanzania-latest.osm.pbf –output map.osm.pbf完美! Dar es Salaam and Zanzibar 的建筑物几何图形存储在 map.osm.pbf 中。RoboSot 利用 rs extract 来从 OSM 的底图提取几何图形。rs extract –type building map.osm.pbf buildings.geojson现在我们从建筑物几何图形的 buildings.geojson 文件提取对应的 Slippy Map tiles 文件,通常设置 zoom level 在19 或者 20 是比较合理的。rs cover –zoom 20 buildings.geojson buildings.tiles基于 buildings.tiles 文件我们可以从 OAM 下载无人机影像并且将它栅格化成对应的OSM蒙版瓦片,下面是一个训练数据的预览效果:如果你自己看会发现这些蒙版其实不是完美匹配的,因为我们训练的模型基于千万个图像和蒙版,有一些噪音数据还是可以接受的。创建无人机图像瓦片最简单的方式是通过 OAM 的 API。 我们可以用 /meta 接口请求所有开放的给定区域的无人机影像。http ‘https://api.openaerialmap.org/meta?bbox=38.9410400390625,-7.0545565715284955,39.70458984374999,-5.711646879515092'JSON 数组是请求的响应,她包含了所有边界框中的无人机影像元信息。我们可以用 jq 来过滤这些网络请求响应,结合比如 通过用户名或者日期这样的过滤条件。jq ‘.results[] | select(.user.name == “ZANZIBAR MAPPING INITIATIVE”) | {user: .user.name, date: .acquisition_start, uuid: .uuid}‘它将返回一个包含对应GeoTIFF图像的 JSON 对象{ “user”: “ZANZIBAR MAPPING INITIATIVE”, “date”: “2017-06-07T00:00:00.000Z”, “uuid”: “https://oin-hotosm.s3.amazonaws.com/5ac7745591b5310010e0d49a/0/5ac7745591b5310010e0d49b.tif"}现在我们有两个选项下载 GeoTIFF 然后用 rasterio 和 rio-tiler 小工具来切割 GeoTIFF生成对应的瓦片。请求 OAM 的 API 直接获取对应的瓦片。rs download https://tiles.openaerialmap.org/5ac626e091b5310010e0d480/0/5ac626e091b5310010e0d481/{z}/{x}/{y}.png building.tiles注意: OAM 提供多个 Slippy Map 接口这两种方法都是为了实现一个目的: 生成一个包含 256x256大小的无人机影像的 Slippy Map。我们可以用提取过的建筑几何边界和瓦片文件创建对应蒙版。rs rasterize –dataset dataset-building.toml –zoom 20 –size 256 buildings.geojson buildings.tiles masks在栅格化之前我们需要创建dataset-building.toml数据集;训练与建模RoboSat 分割模型是一个全连接神经网络,为了保证模型效果,我们进行了数据集切割:80% 训练集,用于模型训练10% 验证集,用户模型效果验证10% 预留集,用户模型超参数调优我们按照上述比例对 building.tiles 文件随机洗牌到不同的 Slippy Map 文件夹下。rs subset images validation.tiles dataset/validation/imagesrs subset masks validation.tiles dataset/validation/labelsrs subset images training.tiles dataset/training/imagesrs subset masks training.tiles dataset/training/labelsrs subset images evaluation.tiles dataset/evaluation/imagesrs subset masks evaluation.tiles dataset/evaluation/labels因为前景和背景在数据集中分布不均,模型训练之前需要先计算一下每个类的分布。rs weights –dataset dataset-building.toml将权重以配置文件的形式保存起来,之后训练会用到。一切都准备好了,可以开始训练了:rs train –model model-unet.toml –dataset dataset-building.toml在训练过程中对于每个 epoch,都会将历史的训练和验证的损失以及指标保存到 checkpoint 中。我们可以在训练过程中选择在 validation 中表现最好的model存在 checkpoint 中。用保存下来的checkpoint能够预测图像中每个像素用以区分前景和背景的所属类别概率,随后这些所属类别概率可转为离散的分割蒙版。rs predict –tile_size 256 –model model-unet.toml –dataset dataset-building.toml –checkpoint checkpoint-00038-of-00050.pth images segmentation-probabilitiesrs masks segmentation-masks segmentation-probabilities这些 Slippy Map 文件夹也可以通过 HTTP 服务器的方式直接对外提供栅格瓦片服务。我们通过 rs serve 也提供按需瓦片服务,它既能有效进行后处理(瓦片边界、去噪音、矢量化,边缘简化)也可以方便地debug。如果你手工检查预测结果你需要注意,本来不存在建筑物但是模型缺圈出来的建筑物是被称为假阳性错误。假阳性错误是因为我们的数据集导致的,我们在数据集中反复采样带有建筑的例子,即使这些瓦片的背景像素不包含足够的背景(被称为负采样)也一样被用来学习勾勒建筑物轮廓。如果我们不反复输入一张图片,那么模型是很难区分出哪些是背景的。解决这个问题有两种方法:添加随机采样的背景瓦片到训练集中,重新计算类的分布权重,然后再次训练,或者使用我们训练好的模型在数据集上反复训练,然后故意在已知无建筑物的样本中进行预测。如果模型出现误判了,然后我们就调出这部分数据集,再次训练。使用所谓的 “硬负挖掘”,允许我们主动添加负样本。这个方法只在小而干净的数据集上使用。对于"硬负挖掘” 我们从不在 building.tiles 的瓦片中随机采样来训练模型。然后通过rs compare 工具创建无建筑的图像,接着进行预测。rs compare visualizations images segmentation-masks在确认真正的背景图片后,不止要在OSM上标注,而且还要找出对应的全背景的负样本到数据集中。接着,走一遍训练流程:rs weights更新配置重新训练通常,在干净的小数据集上做很多遍硬负挖掘和训练才能使得模型收敛。恭喜!你现在有一个鲁棒的模型用于预测了!在花费数小时的硬负样挖掘,我们能产出分割概率了。有趣的看到的是该模型并不完全确定建筑工地。这是因为在我们用硬样挖掘方法选择数据集时决定是否使用建筑工地决定的。最后,后处理流程是有必要的,它将分割蒙版转化为矢量化的 GeoJSON 之后用于瓦片文件生成。本文不对后处理的细节展开,因为基于小样本的训练方式比较粗糙的,RoboSat 后处理模块还在打磨中。总结本教程手把手过了一遍 RoboSat 全流程,从数据集准备、训练分割模型到预测航拍图片中的建筑物。本教程所有工具和数据都开源了。尝试一下吧! https://github.com/mapbox/rob…作为分享主义者(sharism),本人所有互联网发布的图文均遵从CC版权,转载请保留作者信息并注明作者 Harry Zhu 的 FinanceR专栏:https://segmentfault.com/blog…,如果涉及源代码请注明GitHub地址:https://github.com/harryprince。微信号: harryzhustudio商业使用请联系作者。参考资料https://www.openstreetmap.org…https://github.com/mapbox/rob… ...

February 21, 2019 · 2 min · jiezi

使用Opencv构建一个简单的图像相似检测器(MSE、SSIM)

摘要: 本文使用opencv。numpy等简单的工具库,根据mse及ssim两种算法来评估两张图像的相似度,便于理解与实践。介绍作为人类,我们通常非常善于发现图像中的差异。例如,常见的游戏——两张图像找不同。现在让我们玩下这个游戏吧,首先让我们看看上面的图像,三十秒内看看是否能够从中找出有什么不同的地方。答案:水果、冰淇淋和饮料的颜色发生了明显改变,窗帘、太阳也发生了改变,这是不是很简单呢?如果有补充的答案,请在留言处给出哦!这类问题对于人类来说看起来是一件轻而易举的事情,但是,对于计算机来说,这可不是一件容易的事儿。这是由于计算机只能从我们训练它的模型中学习,才最终具有这类能力。目前有很多很好的模型可以对批量图像进行分类,比如TensorFlow和Keras等开源工具。借助于这类开源工具库,计算机视觉领域的研究得以高发展。现在我们也可以借助于这类工具箱创建非常复杂的模型以及解决比较复杂的问题,例如kaggle:Animals-10,该数据集包含数十种不同类型动物的图像以及非动物图像。所要做的就是创建一个模型来预测图片是哪种类型的动物。MSE和SSIM然而,上述任务较为简单,比如常见的手写体数字识别MNIST等,一般也都能取得很高的精度。在这里,我想增加一点难度,创建一个图像分类器,以分辨出两个图像的相似程度。并且,不依赖任何复杂的工具库,如TensorFlow、Keras等。本文采用传统的机器学习方法,这里从中选取两种方法,用于查找图像是否与另一个图像相似。这两种方法分别为均方误差(MSE)、结构相似度指数(SSIM)。上述公式看起来非常复杂,但不要害怕。借助于NumPy,可以相当容易地计算出MSE;另外,由于SSIM是Sci-Kit图像库的内置方法的一部分,因此也可以很容易地计算出SSIM。在进行编码之前,这里先对这两种方法予以简单的说明。MSE将计算正在比较的两个图像的每个像素之间的均方误差。而SSIM做的事情与MSE恰好相反,寻找像素值的相似之处。 也就是,如果两个图像中的像素排列相似或具有相似的像素密度值。MSE方法遇到的一个的问题是其结果往往具有任意大的值,因此很难给出标准的评判标准。一般而言,MSE越高,表明两张图像的相似程度越低。如果图像之间的MSE值是随机值,则很难说明二者是否相似。另一方面,SSIM将所有内容归一化到-1~1的范围内(很难得到小于0的分数)。得分为1表示二者非常相似,得分为-1表示二者非常不同。基于此,SSIM相较于MSE而言是一个更好的衡量指标。实现现在使用代码实现上述想法:加载必要的库:本文使用常见的图像处理工具箱OpenCV实现图像的读取和编辑。如果你对其它图像处理工具箱熟悉,你也可以使用自己熟悉的工具箱完成此类操作,比如matplotlibden。编写MSE公式:使用Numpy操作起来很简单吧!由于SSIM已经通过skimage导入,因此无需进行手动编码。现在创建一个比较函数,该函数的输入为两个图像,分别计算二者的MSE和SSIM,并展示计算结果。下面的三个步骤可以使用for循环一次完成,但是为了更容易地理解,这里不使用for循环编写代码,将其分解为三个部分:首先,加载保存在目录中的图像。其次,必须确保它们的大小相同,否则会出现尺寸不匹配的错误。问题是对其进行尺寸变换操作会导致图像失真,所以在找到比较合适的尺寸数字之前,可以尝试快速搜索方法,尺寸大小按照一定的规律设置,不断实验以找到最终比较合适的尺寸。接下来我们再实现一个功能,以便于看到测试图像是什么样子的。现在通过比较两个一样的图像来测试并查看MSE和SSIM是否正常工作。如果它有效,那么我们应该得到MSE值为0和SSIM值为1的结果。从中可以看到,代码正确,结果与猜想的一致!现在计算机就可以判断比较的两张图像是否相同了。为简单起见,我将三张狗的图像与自己以及三张猫的图像进行比较。下面看看两种算法的性能比较。正如所看到的那样,MSE的值变化很大,因此该值很难说明其表达的意思是什么。但从SSIM的结果看出,可以看到狗2和狗3相对于其他狗的图像最为相似。从视觉上来讲,我同意这个结果,因为两只狗的耳朵非常像。但我还会认为狗1和狗3会有更高的SSIM值,因为二者的姿势也很相似。实际上,在图像没有进行灰度处理之前,狗2和狗3在鼻子区域周围有类似的白色毛皮,而狗1没有。这很可能是狗2和3具有比狗1更高的SSIM值的原因。对于猫来说,这就有点困难。猫1和猫2具有相似的形状,并且图像是从相似的距离拍摄的,但猫2和猫3具有相似的皮毛颜色。这里我想进行的测试只有两个:一个是狗和猫的相似性,第二个是每个动物与原始源代码附带的门图的相似性。正如所预料的那样,狗和猫是相似的,这点与与无生命的物体相比呈鲜明的对比,如侏罗纪公园入口门。狗和猫对门的图像具有较高的SSIM值,唯一原因在于图像都经过了尺寸缩放和灰度处理。在调整图像大小和重新配置时,OpenCV并不是最好的。一般而言,TensorFlow是最好的,TensorFlow也最适合批量图像。之后,我也将使用TensorFlow处理kaggle Animal-10数据集,来实现一个完整的图像分类器。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

January 22, 2019 · 1 min · jiezi

2018最佳GAN论文回顾(下)

摘要: 继上一篇《2018最佳GAN论文回顾(上)》,我又继续介绍了一个对于GAN的基于样式的生成器体系结构的新论文,提出了一个新的模型来应对这种挑战。继上一篇《2018最佳GAN论文回顾(上)》,我又继续介绍了一个对于GAN的基于样式的生成器体系结构的新论文,提出了一个新的模型来应对这种挑战。一种用于生成式对抗网络的基于生成器体系结构的方式 (A Style-Based Generator Architecture for Generative Adversarial Networks)这是NVIDIA的一篇新论文,一个对于GAN(StyleGAN)的基于样式的生成器体系结构,提出了一个新的模型来应对这个挑战。StyleGAN是一步一步地生成人工图像的,从非常低的分辨率开始,一直到高分辨率(1024×1024)。通过分别地修改网络中每个级别的输入,它可以控制在该级别中所表示的视觉特征,从粗糙的特征(姿势、面部形状)到精细的细节(头发颜色),而不会影响其它的级别。这种技术不仅可以更好地理解所生成的输出,而且还可以产生最高水平的结果 — 比以前生成的图像看起来更加真实的高分辨率图像。2018年NVIDIA首次使用ProGAN应对这一挑战时,研究人员都无法生成高质量的大图像(如:1024×1024)。ProGAN的关键创新点是渐进式训练 — 它首先使用非常低分辨率的图像(如:4×4)开始训练生成器和识别器,并且每次都增加一个更高分辨率的网络层。这项技术首先通过学习即使在低分辨率图像中也可以显示的基本特征,来创建图像的基本部分,并且随着分辨率的提高和时间的推移,学习越来越多的细节。低分辨率图像的训练不仅简单、快速,而且有助于更高级别的训练,因此,整体的训练也就更快。ProGAN生成高质量的图像,但与大多数模型一样,它控制所生成图像的特定特征的能力非常有限。换句话说,这些特性是互相关联的,因此尝试调整一下输入,即使是一点儿,通常也会同时影响多个特性。一个很好的类比就是基因组,在其中改变一个基因可能影响多个特性。StyleGAN如何工作StyleGAN论文提供了一个升级版本的ProGAN图像生成器,重点关注生成器网络。作者们观察到ProGAN渐进层的一个潜在的好处是,如果使用得当,它们能够控制图像的不同视觉特征。层和分辨率越低,它所影响的特征就越粗糙。本文将这些特征分为三种类型:1、粗糙的—分辨率最高82,影响姿势、一般发型、面部形状等;2、中等的—分辨率为162至322,影响更精细的面部特征、发型、眼睛的睁开或是闭合等;3、高质的—分辨率为642到10242,影响颜色方案(眼睛、头发和皮肤)和微观特征;除ProGAN生成器之外的一些:映射网络映射网络的目标是将输入向量编码为中间向量,中间向量的不同元素控制不同的视觉特征。这是一个非常重要的过程,因为使用输入向量来控制视觉特征的能力是非常有限的,因为它必须遵循训练数据的概率密度。例如,如果黑头发的人的图像在数据集中更常见,那么更多的输入值将会被映射到该特征上。因此,该模型无法将部分输入(向量中的元素)映射到特征上,这一现象被称为特征纠缠。然而,通过使用另一个神经网络,该模型可以生成一个不必遵循训练数据分布的向量,并且可以减少特征之间的相关性。映射网络由8个全连接的层组成,它的输出ⱳ与输入层(512×1)的大小相同。样式模块(AdaIN)AdaIN(自适应实例标准化)模块将映射网络创建的编码信息ⱳ传输到生成的图像中。该模块被添加到合成网络的每个分辨率级别中,并定义该级别中特征的可视化表达式:1、卷积层输出的每个通道首先进行标准化,以确保步骤3的缩放和切换具有预期的效果;2、中间向量ⱳ使用另一个全连接的网络层(标记为A)转换为每个通道的比例和偏差;3、比例和偏差的向量切换卷积输出的每个通道,从而定义卷积中每个过滤器的重要性。这个调优操作将信息从ⱳ转换为可视的表达方式;删除传统输入大多数的模型以及其中的ProGAN使用随机输入来创建生成器的初始图像(即4×4级别的输入)。StyleGAN团队发现图像特征是由ⱳ和AdaIN控制的,因此可以忽略初始输入,并用常量值替代。虽然本文没有解释它为什么能提高性能,但一个保险的假设是它减少了特征纠缠,对于网络在只使用ⱳ而不依赖于纠缠输入向量的情况下更容易学习。随机变化人们的脸上有许多小的特征,可以看作是随机的,例如:雀斑、发髻线的准确位置、皱纹、使图像更逼真的特征以及各种增加输出的变化。将这些小特征插入GAN图像的常用方法是在输入向量中添加随机噪声。然而,在许多情况下,由于上述特征的纠缠现象,控制噪声的影响是很复杂的,从而会导致图像的其它特征受到影响。StyleGAN中的噪声以类似于AdaIN机制的方式添加,在AdaIN模块之前向每个通道添加一个缩放过的噪声,并稍微改变其操作的分辨率级别特征的视觉表达方式。样式混合StyleGAN生成器在合成网络的每个级别中使用了中间向量,这有可能导致网络学习到这些级别是相关的。为了降低相关性,模型随机选择两个输入向量,并为它们生成了中间向量ⱳ。然后,它用第一个输入向量来训练一些网络级别,然后(在一个随机点中)切换到另一个输入向量来训练其余的级别。随机的切换确保了网络不会学习并依赖于一个合成网络级别之间的相关性。虽然它并不会提高所有数据集上的模型性能,但是这个概念有一个非常有趣的副作用 — 它能够以一种连贯的方式来组合多个图像(视频请查看原文)。该模型生成了两个图像A和B,然后通过从A中提取低级别的特征并从B中提取其余特征再组合这两个图像。在W中的截取技巧在生成模型中的一个挑战,是处理在训练数据中表现不佳的地方。这导致了生成器无法学习和创建与它们类似的图像(相反,它会创建效果不好的图像)。为了避免生成较差的图像,StyleGAN截断了中间向量ⱳ,迫使它保持接近“平均”的中间向量。对模型进行训练之后,通过选择多个随机的输入,用映射网络生成它们的中间向量,并计算这些向量的平均值,从而生成“平均”的平均值ⱳ。当生成新的图像时,不用直接使用映射网络的输出,而是将值ⱳ转换为ⱳ_new=ⱳ_avg+�(ⱳ -ⱳ_avg),其中�的值定义了图像与“平均”图像的差异量(以及输出的多样性)。有趣的是,在仿射转换块之前,通过对每个级别使用不同的�,模型可以控制每个特征集与平均值的差异量。微调在ProGAN上,StyleGAN的另外一个改进措施是更新几个网络超参数,例如训练持续时间和损失函数,并将离得最近的放大或缩小尺度替换为双线性采样。结果本文介绍了两个数据集的最新结果,一个是由名人图片组成的— CelebA-HQ,另一个是由“普通”人图片组成的、更加多样化的新数据集— Flickr-Faces-HQ (FFHQ)。下图显示了模型的不同配置的Frèchet inception distance (FID)得分与ProGAN相比,模型在不同配置下的性能(FID得分),分数越低模型越好(来源:StyleGAN)除了这些结果之外,本文还说明了该模型并不仅仅是通过在卧室图像和汽车图像两个数据集上展示其结果而定制的。特征分离为了使关于特征分离的讨论更加的量化,本文提出了两种新的特征分离的测量方法:1、感知路径长度 — 当在两个随机输入之间插入时,测量两个连续图像(它们的VGG16嵌入)之间的差异。剧烈的变化意味着多个特性已经同时改变了,它们有可能会被纠缠;2、线性可分离性 — 是将输入按照二进制类进行分类的能力,如男性和女性。分类越好,特征就越容易区分。通过对输入的向量z和中间向量ⱳ的指标进行比较,作者们发现在ⱳ中的特征很明显地更容易分离。这些指标还表明了在映射网络中选择8个层与选择1到2个层相比的好处。实施细节StyleGAN在CelebA-HQ和FFHQ数据集上接受了为期一周的训练,使用了8个Tesla V100 GPU。它是在TensorFlow中实现的,并且将开源的。结论StyleGAN是一篇突破性的论文,它不仅可以生成高质量的和逼真的图像,而且还可以对生成的图像进行较好的控制和理解,甚至使生成可信度较高的假图像变得比以前更加的容易。在StyleGAN中提出的一些技术,特别是映射网络和自适应实例标准化(AdaIN),可能是未来许多在GAN方面创新的基础。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

January 16, 2019 · 1 min · jiezi

目标检测算法图解:一文看懂RCNN系列算法

摘要: 本文简要介绍图像检测中常用的深度学习方法——RCNN家族系列算法,以图像讲解形式,便于理解。在生活中,经常会遇到这样的一种情况,上班要出门的时候,突然找不到一件东西了,比如钥匙、手机或者手表等。这个时候一般在房间翻一遍各个角落来寻找不见的物品,最后突然一拍大脑,想到在某一个地方,在整个过程中有时候是很着急的,并且越着急越找不到,真是令人沮丧。但是,如果一个简单的计算机算法可以在几毫秒内就找到你要找的物品,你的感受如何?是不是很惊奇!这就是对象检测算法(object detection)的力量。虽然上述举的生活例子只是一个很简单的例子,但对象检测的应用范围很广,跨越多个不同的行业,从全天候监控到智能城市的实时车辆检测等。简而言之,物体检测是强大的深度学习算法中的一个分支。在本文中,我们将深入探讨可以用于对象检测的各种算法。首先从属于RCNN系列算法开始,即RCNN、 Fast RCNN和 Faster RCNN。在之后的文章中,将介绍更多高级算法,如YOLO、SSD等。1.解决对象检测任务的简单方法(使用深度学习)下图说明了对象检测算法是如何工作。图像中的每个对象,从人到风筝都以一定的精度进行了定位和识别。下面从最简单的深度学习方法开始,一种广泛用于检测图像中的方法——卷积神经网络(CNN)。如果读者对CNN算法有点生疏,建议阅读此文。这里仅简要总结一下CNN的内部运作方式:首先将图像作为输入传递到网络,然后通过各种卷积和池化层处理,最后以对象类别的形式获得输出。对于每个输入图像,会得到一个相应的类别作为输出。因此可以使用这种技术来检测图像中的各种对象。1.首先,将图像作为输入;2.然后,将图像分成不同的区域;3.然后,将每个区域视为单独的图像;4.将所有这些区域传递给CNN并将它们分类为各种类别;5.一旦将每个区域划分为相应的类后,就可以组合所有这些区域来获取具有检测到的对象的原始图像:使用这种方法会面临的问题在于,图像中的对象可以具有不同的宽高比和空间位置。例如,在某些情况下,对象可能覆盖了大部分图像,而在其他情况下,对象可能只覆盖图像的一小部分,并且对象的形状也可能不同。基于此,需要划分大量的区域,这会花费大量的计算时间。因此,为了解决这个问题并减少区域数量,可以使用基于区域的CNN,它使用提议方法选择区域。2.基于区域的卷积神经网络2.1 RCNN的思想RCNN算法不是在大量区域上工作,而是在图像中提出了一堆方框,并检查这些方框中是否包含任何对象。RCNN 使用选择性搜索从图像中提取这些框。下面介绍选择性搜索以及它如何识别不同的区域。基本上四个区域形成一个对象:不同的比例、颜色、纹理和形状。选择性搜索在图像中识别这些模式,并基于此提出各种区域。以下是选择性搜索如何工作的简要概述:首先, 将图像作为输入:然后,它生成初始子分段,以便获得多个区域:之后,该技术组合相似区域以形成更大的区域(基于颜色相似性、纹理相似性、尺寸相似性和形状兼容性):最后,这些区域产生最终的对象位置(感兴趣的区域);下面是RCNN检测对象所遵循的步骤的简要总结:1.首先采用预先训练的卷积神经网络;2.重新训练该模型模型——根据需要检测的类别数量来训练网络的最后一层(迁移学习);3.第三步是获取每个图像的感兴趣区域。然后,对这些区域调整尺寸,以便其可以匹配CNN输入大小;4.获取区域后,使用SVM算法对对象和背景进行分类。对于每个类,都训练一个二分类SVM;最后,训练线性回归模型,为图像中每个识别出的对象生成更严格的边界框;[对上述步骤进行图解分析](http://www.robots.ox.ac.uk/~tvg/publications/talks/Fast-rcnn-slides.pdf):首先,将图像作为输入:然后,使用一些提议方法获得感兴趣区域(ROI)(例如,选择性搜索):之后,对所有这些区域调整尺寸,并将每个区域传递给卷积神经网络:然后,CNN为每个区域提取特征,SVM用于将这些区域划分为不同的类别:最后,边界框回归(Bbox reg)用于预测每个已识别区域的边界框:以上就是RCNN检测物体的全部流程。2.2 RCNN的问题从上节内容可以了解到RCNN是如何进行对象检测的,但这种技术有其自身的局限性。以下原因使得训练RCNN模型既昂贵又缓慢:基于选择性搜索算法为每个图像提取2,000个候选区域;使用CNN为每个图像区域提取特征;RCNN整个物体检测过程用到三种模型:CNN模型用于特征提取;线性svm分类器用于识别对象的的类别;回归模型用于收紧边界框;这些过程相结合使得RCNN非常慢,对每个新图像进行预测需要大约40-50秒,这实际上使得模型在面对巨大的数据集时变得复杂且几乎不可能应用。好消息是存在另一种物体检测技术,它解决了RCNN中大部分问题。3.了解Fast RCNN3.1Fast RCNN的思想RCNN的提出者Ross Girshick提出了这样的想法,即每个图像只运行一次CNN,然后找到一种在2,000个区域内共享该计算的方法。在Fast RCNN中,将输入图像馈送到CNN,CNN生成卷积特征映射。使用这些特征图提取候选区域。然后,使用RoI池化层将所有建议的区域重新整形为固定大小,以便将其馈送到全连接网络中。下面将其分解为简化概念的步骤:1.首先将图像作为输入;2.将图像传递给卷积神经网络,生成感兴趣的区域;3.在所有的感兴趣的区域上应用RoI池化层,并调整区域的尺寸。然后,每个区域被传递到全连接层的网络中;4.softmax层用于全连接网以输出类别。与softmax层一起,也并行使用线性回归层,以输出预测类的边界框坐标。因此,Fast RCNN算法中没有使用三个不同的模型,而使用单个模型从区域中提取特征,将它们分成不同的类,并同时返回所标识类的边界框。对上述过程进行可视化讲解:将图像作为输入:将图像传递给卷积神经网络t,后者相应地返回感兴趣的区域:然后,在提取的感兴趣区域上应用RoI池层,以确保所有区域具有相同的大小:最后,这些区域被传递到一个全连接网络,对其进行分类,并同时使用softmax和线性回归层返回边界框:上述过程说明了Fast RCNN是如何解决RCNN的两个主要问题,即将每个图像中的1个而不是2,000个区域传递给卷积神经网络,并使用一个模型来实现提取特征、分类和生成边界框。3.2Fast RCNN的问题Fast RCNN也存在一定的问题,它仍然使用选择性搜索作为查找感兴趣区域的提议方法,这是一个缓慢且耗时的过程,每个图像检测对象大约需要2秒钟。因此,又开发了另一种物体检测算法——Faster RCNN。4.了解Faster RCNN4.1. Faster RCNN的思想Faster RCNN是Fast RCNN的修改版本,二者之间的主要区别在于,Fast RCNN使用选择性搜索来生成感兴趣区域,而Faster RCNN使用“区域提议网络”,即RPN。RPN将图像特征映射作为输入,并生成一组提议对象,每个对象提议都以对象分数作为输出。以下步骤通常采用Faster RCNN方法:1.将图像作为输入并将其传递给卷积神经网络,后者返回该图像的特征图;2.在这些特征图上应用RPN,返回提议对象及其分数;3.在这些提议对象上应用RoI池层,以将所有提案降低到相同的大小;4.最后,将提议传递到全连接层,该层在其顶部具有softmax层和线性回归层,以对对象的边界框进行分类和输出;这里简要解释一下RPN是如何运作的:首先,Faster RCNN从CNN获取特征图并将它们传递到区域提议网络。RPN在这些特征图上使用滑动窗口,每个窗口生成不同形状和大小的k个方框( Anchor boxe):方框是固定尺寸的边界箱,具有不同的形状和尺寸。对于每个方框,RPN预测两件事:预测锚是对象的概率;用于边界框回归器调整锚点以更好地适合物体的形状;在有了不同形状和大小的边界框后,将其传递到RoI池层。对每个提案并对其进行裁剪,以便每个提案都包含一个对象。这就是RoI池层所做的事情,它为每个方框提取固定大小的特征图:然后将这些特征图传递到全连接层,该层具有softmax和线性回归层,最终对对象进行分类并预测已识别对象的边界框。4.2Faster RCNN的问题上述讨论过的所有对象检测算法都使用区域来识别对象,且网络不会一次查看完整图像,而是按顺序关注图像的某些部分,这样会带来两个复杂性的问题:该算法需要多次通过单个图像来提取到所有对象;由于不是端到端的算法,不同的系统一个接一个地工作,整体系统的性能进一步取决于先前系统的表现效果。5.总结下表是总结了本文中介绍的所有算法算法特征预测时间限制CNN将图像分成多个区域,将每个区域分类为不同的类别-需要很多区域来准确预测,因此计算时间长RCNN使用选择性搜索生成区域,从每个图像中提取大约2000个区域40-50秒每个区域分别传递给CNN的计算时间也很长,且使用三种不同的模型进行预测Fast RCNN每个图像只传递一次到CNN,并提取特征图。在这些地图上使用选择性搜索来生成预测。将RCNN中使用的所有三种模型组合在一起2秒选择性搜索很慢,因此计算时间仍然很长Faster RCNN用区域提议网络替换选择性搜索方法,使算法更快0.2秒对象提议需要时间,并且由于不同的系统一个接一个地工作,系统的性能取决于先前系统的表现效果本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

December 14, 2018 · 1 min · jiezi

对象检测(object detection)算法图解

摘要: 本文简要介绍图像检测中常用的深度学习方法——RCNN家族系列算法,以图像讲解形式,便于理解。在生活中,经常会遇到这样的一种情况,上班要出门的时候,突然找不到一件东西了,比如钥匙、手机或者手表等。这个时候一般在房间翻一遍各个角落来寻找不见的物品,最后突然一拍大脑,想到在某一个地方,在整个过程中有时候是很着急的,并且越着急越找不到,真是令人沮丧。但是,如果一个简单的计算机算法可以在几毫秒内就找到你要找的物品,你的感受如何?是不是很惊奇!这就是对象检测算法(object detection)的力量。虽然上述举的生活例子只是一个很简单的例子,但对象检测的应用范围很广,跨越多个不同的行业,从全天候监控到智能城市的实时车辆检测等。简而言之,物体检测是强大的深度学习算法中的一个分支。在本文中,我们将深入探讨可以用于对象检测的各种算法。首先从属于RCNN系列算法开始,即RCNN、 Fast RCNN和 Faster RCNN。在之后的文章中,将介绍更多高级算法,如YOLO、SSD等。1.解决对象检测任务的简单方法(使用深度学习)下图说明了对象检测算法是如何工作。图像中的每个对象,从人到风筝都以一定的精度进行了定位和识别。下面从最简单的深度学习方法开始,一种广泛用于检测图像中的方法——卷积神经网络(CNN)。如果读者对CNN算法有点生疏,建议阅读此文。这里仅简要总结一下CNN的内部运作方式:首先将图像作为输入传递到网络,然后通过各种卷积和池化层处理,最后以对象类别的形式获得输出。对于每个输入图像,会得到一个相应的类别作为输出。因此可以使用这种技术来检测图像中的各种对象。1.首先,将图像作为输入;2.然后,将图像分成不同的区域;3.然后,将每个区域视为单独的图像;4.将所有这些区域传递给CNN并将它们分类为各种类别;5.一旦将每个区域划分为相应的类后,就可以组合所有这些区域来获取具有检测到的对象的原始图像:使用这种方法会面临的问题在于,图像中的对象可以具有不同的宽高比和空间位置。例如,在某些情况下,对象可能覆盖了大部分图像,而在其他情况下,对象可能只覆盖图像的一小部分,并且对象的形状也可能不同。基于此,需要划分大量的区域,这会花费大量的计算时间。因此,为了解决这个问题并减少区域数量,可以使用基于区域的CNN,它使用提议方法选择区域。2.基于区域的卷积神经网络2.1 RCNN的思想RCNN算法不是在大量区域上工作,而是在图像中提出了一堆方框,并检查这些方框中是否包含任何对象。RCNN 使用选择性搜索从图像中提取这些框。下面介绍选择性搜索以及它如何识别不同的区域。基本上四个区域形成一个对象:不同的比例、颜色、纹理和形状。选择性搜索在图像中识别这些模式,并基于此提出各种区域。以下是选择性搜索如何工作的简要概述:首先, 将图像作为输入:然后,它生成初始子分段,以便获得多个区域:之后,该技术组合相似区域以形成更大的区域(基于颜色相似性、纹理相似性、尺寸相似性和形状兼容性):最后,这些区域产生最终的对象位置(感兴趣的区域);下面是RCNN检测对象所遵循的步骤的简要总结:1.首先采用预先训练的卷积神经网络;2.重新训练该模型模型——根据需要检测的类别数量来训练网络的最后一层(迁移学习);3.第三步是获取每个图像的感兴趣区域。然后,对这些区域调整尺寸,以便其可以匹配CNN输入大小;4.获取区域后,使用SVM算法对对象和背景进行分类。对于每个类,都训练一个二分类SVM;最后,训练线性回归模型,为图像中每个识别出的对象生成更严格的边界框;[对上述步骤进行图解分析](http://www.robots.ox.ac.uk/~tvg/publications/talks/Fast-rcnn-slides.pdf):首先,将图像作为输入:然后,使用一些提议方法获得感兴趣区域(ROI)(例如,选择性搜索):之后,对所有这些区域调整尺寸,并将每个区域传递给卷积神经网络:然后,CNN为每个区域提取特征,SVM用于将这些区域划分为不同的类别:最后,边界框回归(Bbox reg)用于预测每个已识别区域的边界框:以上就是RCNN检测物体的全部流程。2.2 RCNN的问题从上节内容可以了解到RCNN是如何进行对象检测的,但这种技术有其自身的局限性。以下原因使得训练RCNN模型既昂贵又缓慢:基于选择性搜索算法为每个图像提取2,000个候选区域;使用CNN为每个图像区域提取特征;RCNN整个物体检测过程用到三种模型:CNN模型用于特征提取;线性svm分类器用于识别对象的的类别;回归模型用于收紧边界框;这些过程相结合使得RCNN非常慢,对每个新图像进行预测需要大约40-50秒,这实际上使得模型在面对巨大的数据集时变得复杂且几乎不可能应用。好消息是存在另一种物体检测技术,它解决了RCNN中大部分问题。3.了解Fast RCNN3.1Fast RCNN的思想RCNN的提出者Ross Girshick提出了这样的想法,即每个图像只运行一次CNN,然后找到一种在2,000个区域内共享该计算的方法。在Fast RCNN中,将输入图像馈送到CNN,CNN生成卷积特征映射。使用这些特征图提取候选区域。然后,使用RoI池化层将所有建议的区域重新整形为固定大小,以便将其馈送到全连接网络中。下面将其分解为简化概念的步骤:1.首先将图像作为输入;2.将图像传递给卷积神经网络,生成感兴趣的区域;3.在所有的感兴趣的区域上应用RoI池化层,并调整区域的尺寸。然后,每个区域被传递到全连接层的网络中;4.softmax层用于全连接网以输出类别。与softmax层一起,也并行使用线性回归层,以输出预测类的边界框坐标。因此,Fast RCNN算法中没有使用三个不同的模型,而使用单个模型从区域中提取特征,将它们分成不同的类,并同时返回所标识类的边界框。对上述过程进行可视化讲解:将图像作为输入:将图像传递给卷积神经网络t,后者相应地返回感兴趣的区域:然后,在提取的感兴趣区域上应用RoI池层,以确保所有区域具有相同的大小:最后,这些区域被传递到一个全连接网络,对其进行分类,并同时使用softmax和线性回归层返回边界框:上述过程说明了Fast RCNN是如何解决RCNN的两个主要问题,即将每个图像中的1个而不是2,000个区域传递给卷积神经网络,并使用一个模型来实现提取特征、分类和生成边界框。3.2Fast RCNN的问题Fast RCNN也存在一定的问题,它仍然使用选择性搜索作为查找感兴趣区域的提议方法,这是一个缓慢且耗时的过程,每个图像检测对象大约需要2秒钟。因此,又开发了另一种物体检测算法——Faster RCNN。4.了解Faster RCNN4.1. Faster RCNN的思想Faster RCNN是Fast RCNN的修改版本,二者之间的主要区别在于,Fast RCNN使用选择性搜索来生成感兴趣区域,而Faster RCNN使用“区域提议网络”,即RPN。RPN将图像特征映射作为输入,并生成一组提议对象,每个对象提议都以对象分数作为输出。以下步骤通常采用Faster RCNN方法:1.将图像作为输入并将其传递给卷积神经网络,后者返回该图像的特征图;2.在这些特征图上应用RPN,返回提议对象及其分数;3.在这些提议对象上应用RoI池层,以将所有提案降低到相同的大小;4.最后,将提议传递到全连接层,该层在其顶部具有softmax层和线性回归层,以对对象的边界框进行分类和输出;这里简要解释一下RPN是如何运作的:首先,Faster RCNN从CNN获取特征图并将它们传递到区域提议网络。RPN在这些特征图上使用滑动窗口,每个窗口生成不同形状和大小的k个方框( Anchor boxe):方框是固定尺寸的边界箱,具有不同的形状和尺寸。对于每个方框,RPN预测两件事:预测锚是对象的概率;用于边界框回归器调整锚点以更好地适合物体的形状;在有了不同形状和大小的边界框后,将其传递到RoI池层。对每个提案并对其进行裁剪,以便每个提案都包含一个对象。这就是RoI池层所做的事情,它为每个方框提取固定大小的特征图:然后将这些特征图传递到全连接层,该层具有softmax和线性回归层,最终对对象进行分类并预测已识别对象的边界框。4.2Faster RCNN的问题上述讨论过的所有对象检测算法都使用区域来识别对象,且网络不会一次查看完整图像,而是按顺序关注图像的某些部分,这样会带来两个复杂性的问题:该算法需要多次通过单个图像来提取到所有对象;由于不是端到端的算法,不同的系统一个接一个地工作,整体系统的性能进一步取决于先前系统的表现效果。5.总结下表是总结了本文中介绍的所有算法算法特征预测时间限制CNN将图像分成多个区域,将每个区域分类为不同的类别-需要很多区域来准确预测,因此计算时间长RCNN使用选择性搜索生成区域,从每个图像中提取大约2000个区域40-50秒每个区域分别传递给CNN的计算时间也很长,且使用三种不同的模型进行预测Fast RCNN每个图像只传递一次到CNN,并提取特征图。在这些地图上使用选择性搜索来生成预测。将RCNN中使用的所有三种模型组合在一起2秒选择性搜索很慢,因此计算时间仍然很长Faster RCNN用区域提议网络替换选择性搜索方法,使算法更快0.2秒对象提议需要时间,并且由于不同的系统一个接一个地工作,系统的性能取决于先前系统的表现效果本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

December 12, 2018 · 1 min · jiezi

资深程序员的Metal入门教程总结

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~本文由落影发表于云+社区专栏正文本文介绍Metal和Metal Shader Language,以及Metal和OpenGL ES的差异性,也是实现入门教程的心得总结。一、MetalMetal 是一个和 OpenGL ES 类似的面向底层的图形编程接口,可以直接操作GPU;支持iOS和OS X,提供图形渲染和通用计算能力。(不支持模拟器)图片来源 https://www.invasivecode.com/...MTLDevice 对象代表GPU,通常使用MTLCreateSystemDefaultDevice获取默认的GPU; MTLCommandQueue由device创建,用于创建和组织MTLCommandBuffer,保证指令(MTLCommandBuffer)有序地发送到GPU;MTLCommandBuffer会提供一些encoder,包括编码绘制指令的MTLRenderCommandEncoder、编码计算指令的MTLComputeCommandEncoder、编码缓存纹理拷贝指令的MTLBlitCommandEncoder。对于一个commandBuffer,只有调用encoder的结束操作,才能进行下一个encoder的创建,同时可以设置执行完指令的回调。 每一帧都会产生一个MTLCommandBuffer对象,用于填放指令; GPUs的类型很多,每一种都有各自的接收和执行指令方式,在MTLCommandEncoder把指令进行封装后,MTLCommandBuffer再做聚合到一次提交里。 MTLRenderPassDescriptor 是一个轻量级的临时对象,里面存放较多属性配置,供MTLCommandBuffer创建MTLRenderCommandEncoder对象用。MTLRenderPassDescriptor 用来更方便创建MTLRenderCommandEncoder,由MetalKit的view设置属性,并且在每帧刷新时都会提供新的MTLRenderPassDescriptor;MTLRenderCommandEncoder在创建的时候,会隐式的调用一次clear的命令。 最后再调用present和commit接口。Metal的viewport是3D的区域,包括宽高和近/远平面。深度缓冲最大值为1,最小值为0,如下面这两个都不会显示。 // clipSpacePosition为深度缓冲 out.clipSpacePosition = vector_float4(0.0, 0.0, -0.1, 1.0); out.clipSpacePosition = vector_float4(0.0, 0.0, 1.1, 1.0);渲染管道Metal把输入、处理、输出的管道看成是对指定数据的渲染指令,比如输入顶点数据,输出渲染后纹理。 MTLRenderPipelineState 表示渲染管道,最主要的三个过程:顶点处理、光栅化、片元处理:转换几何形状数据为帧缓存中的颜色像素,叫做点阵化(rasterizing),也叫光栅化。其实就是根据顶点的数据,检测像素中心是否在三角形内,确定具体哪些像素需要渲染。 对开发者而言,顶点处理和片元处理是可编程的,光栅化是固定的(不可见)。 顶点函数在每个顶点被绘制时都会调用,比如说绘制一个三角形,会调用三次顶点函数。顶点处理函数返回的对象里,必须有带[[position]]描述符的属性,表面这个属性是用来计算下一步的光栅化;返回值没有描述符的部分,则会进行插值处理。插值处理像素处理是针对每一个要渲染的像素进行处理,返回值通常是4个浮点数,表示RGBA的颜色。 在编译的时候,Xcode会单独编译.metal的文件,但不会进行链接;需要在app运行时,手动进行链接。 在包里,可以看到default.metallib,这是对metal shader的编译结果。MTLFunction可以用来创建MTLRenderPipelineState对象,MTLRenderPipelineState代表的是图形渲染的管道; 在调用device的newRenderPipelineStateWithDescriptor:error接口时,会进行顶点、像素函数的链接,形成一个图像处理管道; MTLRenderPipelineDescriptor包括名称、顶点处理函数、片元处理函数、输出颜色格式。setVertexBytes:length:atIndex:这接口的长度限制是4k(4096bytes),对于超过的场景应该使用MTLBuffer。MTLBuffer是GPU能够直接读取的内存,用来存储大量的数据;(常用于顶点数据) newBufferWithLength:options:方法用来创建MTLBuffer,参数是大小和访问方式;MTLResourceStorageModeShared是默认的访问方式。纹理Metal要求所有的纹理都要符合MTLPixelFormat上面的某一种格式,每个格式都代表对图像数据的不同描述方式。 例如MTLPixelFormatBGRA8Unorm格式,内存布局如下: 每个像素有32位,分别代表BRGA。 MTLTextureDescriptor 用来设置纹理属性,例如纹理大小和像素格式。 MTLBuffer用于存储顶点数据,MTLTexture则用于存储纹理数据;MTLTexture在创建之后,需要调用replaceRegion:mipmapLevel:withBytes:bytesPerRow:填充纹理数据;因为图像数据一般按行进行存储,所以需要每行的像素大小。[[texture(index)]] 用来描述纹理参数,比如说 samplingShader(RasterizerData in [[stage_in]], texture2d<half> colorTexture [[ texture(AAPLTextureIndexBaseColor) ]]) 在读取纹理的时候,需要两个参数,一个是sampler和texture coordinate,前者是采样器,后者是纹理坐标。 读取纹理其实就把对应纹理坐标的像素颜色读取出来。 纹理坐标默认是(0,0)到(1,1),如下: 有时候,纹理的坐标会超过1,采样器会根据事前设置的mag_filter::参数进行计算。通用计算通用图形计算是general-purpose GPU,简称GPGPU。 GPU可以用于加密、机器学习、金融等,图形绘制和图形计算并不是互斥的,Metal可以同时使用计算管道进行图形计算,并且用渲染管道进行渲染。计算管道只有一个步骤,就是kernel function(内核函数),内核函数直接读取并写入资源,不像渲染管道需要经过多个步骤; MTLComputePipelineState 代表一个计算处理管道,只需要一个内核函数就可以创建,相比之下,渲染管道需要顶点和片元两个处理函数;每次内核函数执行,都会有一个唯一的gid值; 内核函数的执行次数需要事先指定,这个次数由格子大小决定。threadgroup 指的是设定的处理单元,这个值要根据具体的设备进行区别,但必须是足够小的,能让GPU执行; threadgroupCount 是需要处理的次数,一般来说threadgroupCount*threadgroup=需要处理的大小。性能相关临时对象(创建和销毁是廉价的,它们的创建方法都返回 autoreleased对象) 1.Command Buffers 2.Command Encoders 代码中不需要持有。高消耗对象(在性能相关的代码里应该尽量重用它,避免反复创建) 1.Command Queues 2.Buffers 3.Textures 5.Compute States 6.Render Pipeline States 代码中需长期持有。Metal常用的四种数据类型:half、float、short(ushort)、int(uint)。 GPU的寄存器是16位,half是性能消耗最低的数据类型;float需要两次读取、消耗两倍的寄存器空间、两倍的带宽、两倍的电量。 为了提升性能,half和float之间的转换由硬件来完成,不占用任何开销。 同时,Metal自带的函数都是经过优化的。 在float和half数据类型混合的计算中,为了保持精度会自动将half转成float来处理,所以如果想用half节省开销的话,要避免和float混用。 Metal同样不擅长处理control flow,应该尽可能使用使用三元表达式,取代简单的if判断。此部分参考自WWDC常见的图形渲染管道二、Metal Shader LanguageMetal Shader Language的使用场景有两个,分别是图形渲染和通用计算;基于C++ 14,运行在GPU上,GPU的特点:带宽大,并行处理,内存小,对条件语句处理较慢(等待时间长)。 Metal着色语言使用clang和 LLVM,支持重载函数,但不支持图形渲染和通用计算入口函数的重载、递归函数调用、new和delete操作符、虚函数、异常处理、函数指针等,也不能用C++ 11的标准库。基本函数shader有三个基本函数:顶点函数(vertex),对每个顶点进行处理,生成数据并输出到绘制管线;像素函数(fragment),对光栅化后的每个像素点进行处理,生成数据并输出到绘制管线;通用计算函数(kernel),是并行计算的函数,其返回值类型必须为void;顶点函数相关的修饰符:[[vertex_id]] vertex_id是顶点shader每次处理的index,用于定位当前的顶点[[instance_id]] instance_id是单个实例多次渲染时,用于表明当前索引;[[clip_distance]],float 或者 float[n], n必须是编译时常量;[[point_size]],float;[[position]],float4;如果一个顶点函数的返回值不是void,那么返回值必须包含顶点位置; 如果返回值是float4,默认表示位置,可以不带[[ position ]]修饰符; 如果一个顶点函数的返回值是结构体,那么结构体必须包含“[[ position ]]”修饰的变量。像素函数相关的修饰符:[[color(m)]] float或half等,m必须是编译时常量,表示输入值从一个颜色attachment中读取,m用于指定从哪个颜色attachment中读取;[[front_facing]] bool,如果像素所属片元是正面则为true;[[point_coord]] float2,表示点图元的位置,取值范围是0.0到1.0;[[position]] float4,表示像素对应的窗口相对坐标(x, y, z, 1/w);[[sample_id]] uint,The sample number of the sample currently being processed.[[sample_mask]] uint,The set of samples covered by the primitive generating the fragmentduring multisample rasterization.以上都是输入相关的描述符。像素函数的返回值是单个像素的输出,包括一个或是多个渲染结果颜色值,一个深度值,还有一个sample遮罩,对应的输出描述符是[[color(m)]] floatn、[[depth(depth_qualifier)]] float、[[sample_mask]] uint。struct LYFragmentOutput { // color attachment 0 float4 color_float [[color(0)]];// color attachment 1 int4 color_int4 [[color(1)]];// color attachment 2 uint4 color_uint4 [[color(2)]];};fragment LYFragmentOutput fragment_shader( … ) { … };需要注意,颜色attachment的参数设置要和像素函数的输入和输出的数据类型匹配。Metal支持一个功能,叫做前置深度测试(early depth testing),允许在像素着色器运行之前运行深度测试。如果一个像素被覆盖,则会放弃渲染。使用方式是在fragment关键字前面加上[[early_fragment_tests]]: [[early_fragment_tests]] fragment float4 samplingShader(..) 使用前置深度测试的要求是不能在fragment shader对深度进行写操作。 深度测试还不熟悉的,可以看LearnOpenGL关于深度测试的介绍。参数的地址空间选择Metal种的内存访问主要有两种方式:Device模式和Constant模式,由代码中显式指定。 Device模式是比较通用的访问模式,使用限制比较少,而Constant模式是为了多次读取而设计的快速访问只读模式,通过Constant内存模式访问的参数的数据的字节数量是固定的,特点总结为:Device支持读写,并且没有size的限制;Constant是只读,并且限定大小;如何选择Device和Constant模式? 先看数据size是否会变化,再看访问的频率高低,只有那些固定size且经常访问的部分适合使用constant模式,其他的均用Device。// Metal关键函数用到的指针参数要用地址空间修饰符(device, threadgroup, or constant) 如下vertex RasterizerData // 返回给片元着色器的结构体vertexShader(uint vertexID [[ vertex_id ]], // vertex_id是顶点shader每次处理的index,用于定位当前的顶点 constant LYVertex *vertexArray [[ buffer(0) ]]); // buffer表明是缓存数据,0是索引地址空间的修饰符共有四个,device、threadgroup、constant、thread。 顶点函数(vertex)、像素函数(fragment)、通用计算函数(kernel)的指针或引用参数,都必须带有地址空间修饰符号。 对于顶点函数(vertex)和像素函数(fragment),其指针或引用参数必须定义在device或是constant地址空间; 对于通用计算函数(kernel),其指针或引用参数必须定义在device或是threadgroup或是constant地址空间; void tranforms(device int *source_data, threadgroup int dest_data, constant float param_data) {/…/}; 如上使用了三种地址空间修饰符,因为有threadgroup修饰符,tranforms函数只能被通用计算函数调用。constant地址空间用于从设备内存池分配存储的缓存对象,是只读的。constant地址空间的指针或引用可以做函数的参数,向声明为常量的变量赋值会产生编译错误,声明常量但是没有赋予初始值也会产生编译错误。 在shader中,函数之外的变量(相当于全局变量),其地址空间必须是constant。device地址空间用于从设备内存池分配出来的缓存对象,可读也可写。一个缓存对象可以被声明成一个标量、向量或是用户自定义结构体的指针或是引用。缓存对象使用的内存实际大小,应该在CPU侧调用时就确定。 纹理对象总是在device地址空间分配内存,所以纹理类型可以省略修饰符。threadgroup地址空间用于通用计算函数变量的内存分配,变量被一个线程组的所有的线程共享,threadgroup地址空间分配的变量不能用于图形绘制函数。thread地址空间用于每个线程内部的内存分配,被thread修饰的变量在其他线程无法访问,在图形绘制或是通用计算函数内声明的变量是thread地址空间分配。 如下一段代码,包括device、threadgroup、thread的使用:typedef struct{ half3 kRec709Luma; // position的修饰符表示这个是顶点 } TransParam;kernel voidsobelKernel(texture2d<half, access::read> sourceTexture [[texture(LYFragmentTextureIndexTextureSource)]], texture2d<half, access::write> destTexture [[texture(LYFragmentTextureIndexTextureDest)]], uint2 grid [[thread_position_in_grid]], device TransParam *param [[buffer(0)]], // param.kRec709Luma = half3(0.2126, 0.7152, 0.0722); // 把rgba转成亮度值 threadgroup float3 *localBuffer [[threadgroup(0)]]) // threadgroup地址空间,这里并没有使用到;{ // 边界保护 if(grid.x <= destTexture.get_width() && grid.y <= destTexture.get_height()) { thread half4 color = sourceTexture.read(grid); // 初始颜色 thread half gray = dot(color.rgb, half3(param->kRec709Luma)); // 转换成亮度 destTexture.write(half4(gray, gray, gray, 1.0), grid); // 写回对应纹理 }}数据结构Metal中常用的数据结构有向量、矩阵、原子数据类型、缓存、纹理、采样器、数组、用户自定义结构体。half 是16bit是浮点数 0.5h float 是32bit的浮点数 0.5f size_t 是64bit的无符号整数 通常用于sizeof的返回值 ptrdiff_t 是64bit的有符号整数 通常用于指针的差值 half2、half3、half4、float2、float3、float4等,是向量类型,表达方式为基础类型+向量维数。矩阵类似half4x4、half3x3、float4x4、float3x3。 double、long、long long不支持。对于向量的访问,比如说vec=float4(1.0f, 1.0f, 1.0f, 1.0f),其访问方式可以是vec[0]、vec[1],也可以是vec.x、vec.y,也可以是vec.r、vec.g。(.xyzw和.rgba,前者对应三维坐标,后者对应RGB颜色空间) 只取部分、乱序取均可,比如说我们常用到的color=texture.bgra。数据对齐 char3、uchar3的size是4Bytes,而不是3Bytes; 类似的,int是4Bytes,但int3是16而不是12Bytes; 矩阵是由一组向量构成,按照向量的维度对齐;float3x3由3个float3向量构成,那么每个float3的size是16Bytes; 隐式类型转换(Implicit Type Conversions) 向量到向量或是标量的隐式转换会导致编译错误,比如int4 i; float4 f = i; // compile error,无法将一个4维的整形向量转换为4维的浮点向量。 标量到向量的隐式转换,是标量被赋值给向量的每一个分量。 float4 f = 2.0f; // f = (2.0f, 2.0f, 2.0f, 2.0f) 标量到矩阵、向量到矩阵的隐式转换,矩阵到矩阵和向量及标量的隐式转换会导致编译错误。纹理数据结构不支持指针和引用,纹理数据结构包括精度和access描述符,access修饰符描述纹理如何被访问,有三种描述符:sample、read、write,如下:kernel voidsobelKernel(texture2d<half, access::read> sourceTexture [[texture(LYFragmentTextureIndexTextureSource)]], texture2d<half, access::write> destTexture [[texture(LYFragmentTextureIndexTextureDest)]], uint2 grid [[thread_position_in_grid]])Sampler是采样器,决定如何对一个纹理进行采样操作。寻址模式,过滤模式,归一化坐标,比较函数。 在Metal程序里初始化的采样器必须使用constexpr修饰符声明。 采样器指针和引用是不支持的,将会导致编译错误。 constexpr sampler textureSampler (mag_filter::linear, min_filter::linear); // sampler是采样器运算符矩阵相乘有一个操作数是标量,那么这个标量和矩阵中的每一个元素相乘,得到一个和矩阵有相同行列的新矩阵。右操作数是一个向量,那么它被看做一个列向量,如果左操作数是一个向量,那么他被看做一个行向量。这个也说明,为什么我们要固定用mvp乘以position(左乘矩阵),而不能position乘以mvp!因为两者的处理结果不一致。三、Metal和OpenGL ES的差异OpenGL的历史已经超过25年。基于当时设计原则,OpenGL不支持多线程,异步操作,还有着臃肿的特性。为了更好利用GPU,苹果设计了Metal。 Metal的目标包括更高效的CPU&GPU交互,减少CPU负载,支持多线程执行,可预测的操作,资源控制和同异步控制;接口与OpenGL类似,但更加切合苹果设计的GPUs。Metal的关系图Metal的关系图如上,其中的Device是GPU设备的抽象,负责管道相关对象的创建:DeviceMetal和OpenGL ES的代码对比我们先看一段OpenGL ES的渲染代码,我们可以抽象为Render Targets的设定,Shaders绑定,设置Vertex Buffers、Uniforms和Textures,最后调用Draws指令。glBindFramebuffer(GL_FRAMEBUFFER, myFramebuffer);glUseProgram(myProgram);glBindBuffer(GL_ARRAY_BUFFER, myVertexBuffer);glBindBuffer(GL_UNIFORM_BUFFER, myUniforms);glBindTexture(GL_TEXTURE_2D, myColorTexture);glDrawArrays(GL_TRIANGLES, 0, numVertices);再看Metal的渲染代码: Render Targets设定 是创建encoder; Shaders绑定 是设置pipelineState; 设置Vertex Buffers、Uniforms和Textures 是setVertexBuffer和setFragmentBuffer; 调用Draws指令 是drawPrimitives; 最后需要再调用一次endEncoding。encoder = [commandBuffer renderCommandEncoderWithDescriptor:descriptor]; [encoder setPipelineState:myPipeline];[encoder setVertexBuffer:myVertexData offset:0 atIndex:0];[encoder setVertexBuffer:myUniforms offset:0 atIndex:1];[encoder setFragmentBuffer:myUniforms offset:0 atIndex:1];[encoder setFragmentTexture:myColorTexture atIndex:0];[encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:numVertices];[encoder endEncoding];Metal和OpenGL ES的同异步处理如下图,是用OpenGL ES实现一段渲染的代码。CPU在Frame1的回调中写入数据到buffer,之后GPU会从buffer中读取Frame1写入的数据。但在Frame2 CPU在往Buffer写入数据时,Buffer仍存储着Frame1的数据,且GPU还在使用该buffer,于是Frame2必须等待Frame1渲染完毕,造成阻塞。如下,会产生CPU的wait和GPU的idle。Metal的处理方案会更加高效。如下图,Metal会申请三个buffer对应三个Frame,然后根据GPU的渲染回调,实时更新buffer的缓存。 在Frame2的时候,CPU会操作Buffer2,而GPU会读取Buffer1,并行操作以提高效率。总结Metal系列入门教程介绍了Metal的图片绘制、三维变换、视频渲染、天空盒、计算管道、Metal与OpenGL ES交互。结合本文的总结,能对Metal产生基本的认知,看懂大部分Metal渲染的代码。 接下来的学习方向是Metal进阶,包括Metal滤镜链的设计与实现、多重colorAttachments渲染、绿幕功能实现、更复杂的通用计算比如MPSImageHistogram,Shader的性能优化等。相关阅读【每日课程推荐】机器学习实战!快速入门在线广告业务及CTR相应知识 ...

November 1, 2018 · 2 min · jiezi