当前位置: 首页 > 科技观察

有趣的6种图像灰度转换算法

时间:2023-03-22 15:34:30 科技观察

【引自杨景卓博客】前言虽然黑白照片的时代已经过去,但是现在翻看以前的照片,是不是有一种回到过去的感觉,很酷还有木本的~看完这篇文章,你可以把彩色照片变成各种黑白照片。本文是一个完整的在线实例图像灰度算法实例。示例中图片较多,可能会有点慢。该示例的源代码位于博客/演示中。三原色和灰度原色是指不能通过其他颜色混合搭配得到的“基本色”。一般来说,加色型的三基色是红、绿、蓝。将原色按不同比例混合可以产生其他新的颜色。这种原色系统常被称为“RGB色彩空间”,即由红(R)、绿(G)、蓝(B)组成的色系。当这三种原色按等比例叠加在一起时,就会变成灰色;如果将这三种原色的强度调到最高,并且等量重叠,就会呈现白色。灰度表示没有颜色,RGB颜色分量都是相等的。获取图片的像素数据算法不区分语言。这是前端的示例。可以使用canvas获取图片某个区域的像素数据//伪代码varimg=newImage();img.src='xxx.jpg';varmyCanvas=document.querySelector(canvasId);varcanvasCtx=myCanvas。getContext("2d");canvasCtx.drawImage(img,0,0,img.width,img.height);//图片像素数据vardata=canvasCtx.getImageData(0,0,img.width,img.height);使用getImageData()返回一个ImageData对象,这个对象有一个data属性就是我们要的数据,data是Uint8ClampedArray描述的一维数组,包含RGBA顺序的数据,数据用整数表示从0到255(含)。所以一个像素点会有4个数据(RGBA),RGB就是红绿蓝,A指的是透明度。例如:本文720*480的水果图片一共有720*480=259200个像素点,每个像素点有4个数据,所以数据数组的总长度为259200*4=1036800。可以看到图片的数据很长。如果一次处理很多张图片,计算量是相当可观的,所以例子中会使用worker将繁重的计算任务交给后台线程处理。算法的基本步骤获取每个像素点的红绿蓝值。使用灰度算法计算灰度值。使用此灰度值替换像素的原始红色、绿色和蓝色值。比如我们的灰度算法是:Gray=(Red+Green+Blue)/3计算过程://pseudocodefor(varPixelinImage){varRed=Image[Pixel].RedvarGreen=Image[Pixel].GreenvarBlue=Image[Pixel].BluevarGray=(Red+Green+Blue)/3Image[Pixel].Red=GrayImage[Pixel].Green=GrayImage[Pixel].Blue=Gray}很简单吧?很多美味鲜艳的水果,但它们快要变灰了!!算法1——平均法使用算法1:这是最常见的灰度算法,简单暴力,放在第一位。公式为:Gray=(Red+Green+Blue)/3这个算法可以产生很好的灰度值,因为公式简单,所以容易维护和优化。但是,它也不是没有缺点,因为它简单、速度快,而且从人的感知来看,画面的灰度阴影和亮度不够好。因此,我们需要更复杂的计算。算法2——基于人的感知使用算法2:算法1和算法2生成的图片好像是一样的,所以加个例子图片上半部分使用算法1,下半部分使用算法2。上半部分是算法1,下半部分是算法2:仔细看,中间有一条黑线。上半部分(算法1)比下半部分(算法2)稍微浅一些。如果还是看不到,注意最右边的柠檬。算法1的柠檬比较反光,算法2的柠檬比较软。第二种算法考虑到人眼对不同级别的光的感知不同。人眼中有几种锥形感光细胞,对黄绿光、绿光和蓝紫光最为敏感。虽然眼球中的脊椎细胞对红、绿、蓝三种颜色不是最敏感的,但是肉眼的脊椎细胞所能感知的光带宽非常大,红、绿、蓝也能刺激这些颜色独立。三种颜色的感光器。人对红绿蓝的感知顺序是:绿>红>蓝,所以从这个角度看一般的算法是不科学的。应根据人对光的感知程度,为每种颜色设置一个权重,它们的地位不应该相等。一个常用的图像处理公式是:Gray=(Red*0.3+Green*0.59+Blue*0.11)可以看出每种颜色的系数差异很大。现在对于图像灰度处理的最优公式还存在争议。还有一些类似的公式:Gray=(Red*0.2126+Green*0.7152+Blue*0.0722)orGray=(Red*0.299+Green*0.587+Blue*0.114)它们只是系数有些偏差,一般的比例是差不多一样。Algorithm3-DesaturationUsingAlgorithm3:在谈论这个算法之前,让我们先谈谈RGB。大多数程序员使用RGB模型。每种颜色都可以由红色、绿色和蓝色组成。RGB对计算机非常有用。描述颜色,但人类很难理解。如果你在升国旗的时候说,“五星红旗是RGB(255,0,42)”,你可能会被狠狠揍一顿。但当我说出鲜红的五星级红旗时,老师可能会点头称赞。所以为了更容易理解,有时我们会选择HLS模型来描述颜色。这三个字母分别代表Hue(色调)、Saturation(饱和度)和Lightness(亮度)。色调,取值为:0-360,0(或360)表示红色,120表示绿色,240表示蓝色,也可以用其他值来指定颜色。饱和度,取值范围:0.0%-100.0%,通常指颜色的鲜艳程度。亮度,取值为:0.0%-100.0%,黑色的亮度为0。去饱和的过程就是将RGB转为HLS,然后将饱和度设置为0。因此,我们需要取一个颜色,转为最小饱和值。这个数学公式比本文中介绍的更复杂。这是一个简单的公式,其中可以通过计算RGB中最小值和最大值之间的中值来使像素去饱和:Gray=(Math.max(Red,Green,Blue)+Math.min(Red,Green,Blue))/2去饱和后,画面的立体感减弱了,反而更柔和了。比较算法2,我们可以清楚地看到差异。从效果来看,大多数人可能会喜欢算法2,而算法3是迄今为止处理的最弱、最暗的图像。算法4-分解取最大值和取最小值分解算法可以被认为是一种更简单的去饱和方法。分解是以每个像素为单位,只取RGB的最大值或最小值。最大值分解:Gray=Math.max(Red,Green,Blue)最小值分解:Gray=Math.min(Red,Green,Blue)如上所示,最大值分解提供了更亮的图形,而最小值分解提供了一个更黑暗的情节。算法5-一种通过对单个通道采用红色通道、绿色通道和蓝色通道来将图像变灰的更快方法。该方法不需要做任何计算,直接将某个通道的值作为灰度值。Gray=RedorGray=GreenorGray=Blue信不信由你,大多数数码相机都使用这种算法来生成灰度图像。这种变换的结果很难预测,所以这种算法主要用于艺术效果。算法6-自定义灰度阴影NumberOfShades=4这是迄今为止最有趣的算法,允许用户提供2-256范围内的灰度值阴影。2的结果是全白图像,256的结果和算法1是一样的。NumberOfShades=16此算法通过选择色度值来工作,其公式有点复杂ConversionFactor=255/(NumberOfShades-1)AverageValue=(Red+Green+Blue)/3Gray=Math.round((AverageValue/ConversionFactor)+0.5)*ConversionFactorNumberOfShades的范围是2-256。从技术上讲,任何灰度算法都可以计算AverageValue,它只提供初始灰度的估计值。“+0.5”是模拟舍入的可选参数。部分这是一篇非常有趣的文章。它不仅介绍了灰度算法,而且有助于理解图像处理的过程。