Javascript图像处理—亮度对比度应用案例

前言

上一篇文章,我们讲解了图像处理中的卷积操作和平滑(也就是模糊)处理,这篇文章我们进行亮度和对比度的变化。

其实,亮度是啥玩意?

亮度就是比较亮眼咯……

实际上对于RGBA颜色空间,变亮其实就等于R、G、B三个通道同时加大,那么变暗就等于同时减小咯。

这比较好理解,因为最暗的黑色是RGB(0,0,0),而最亮的白色是RGB(255,255,255)。所以变亮应该RGB各通道都要增大。

那么,对比度呢?

对比度,其实就是颜色差啦。

那么对于RGBA颜色空间,对比度变大其实就等于R、G、B三个通道同时乘以一个比例,因为这样相近的颜色之间的差距就变大了,那么减小就是同时除以咯。

举个例子,原来RGB(23,44,55)和RGB(33,44,55)相差只有10,但是一起乘以2以后,就变成了RGB(46,88,110)和RGB(66,88,110)

,相差变成了20了,也就是“颜色差”变大了。

线性模型

newRGB =  Contrast * RGB + Brightness

线性模型满足上述公式,其中 Contrast表示对比度系数,Brightness表示亮度系数。

线性模型实现比较简单,但是很容易就调出全白或者全黑的图片,对于普通用户来说ContrastBrightness选多少比较好也比较难确定。

所以,实际上在Photoshop里面使用的并不是线性模型,而是非线性模型。

非线性模型

非线性模型中对比度增大和阈值Threshold有关:

当Contrast >= 0时:

newRGB = RGB + (RGB - Threshold) * (1 / (1 - Contrast / 255) - 1)

当Contrast < 0时:

newRGB = RGB + (RGB - Threshold) * Contrast / 255

那么当对比度和亮度同时调整时候呢?

如果对比度大于0,先调整亮度,再调整对比度;当对比度小于0时,则相反,先调整对比度,再调整亮度。

最后一个问题,阈值Threshold到底是什么,其实这个是图片的灰度平均值。

实现代码


代码如下:

var brightnessContrast = function(__src, __brightness, __contrast){
__src || error(arguments.callee, IS_UNDEFINED_OR_NULL/* {line} */);
if(__src.type === "CV_RGBA"){
var sData = __src.data,
width = __src.col,
height = __src.row,
dst = new Mat(height, width, CV_RGBA),
dData = dst.data,
brightness = Math.max(-255, Math.min(255, __brightness || 0)),
contrast = Math.max(-255, Math.min(255, __contrast || 0));

var gray = cvtColor(__src, CV_RGBA2GRAY),
allValue = 0,
gData = gray.data;
var y, x, c;

for(y = height; y--;){
for(x = width; x--;){
allValue += gData[y * width + x];
}
}

var r, g, b, offset, gAverage = (allValue / (height * width)) | 0;

for(y = height; y--;){
for(x = width; x--;){
offset = (y * width + x) * 4;
dData[offset] = sData[offset] + brightness;
dData[offset + 1] = sData[offset + 1] + brightness;
dData[offset + 2] = sData[offset + 2] + brightness;

if(contrast >= 0){
for(c = 3; c--;){
if(dData[offset + c] >= gAverage){
dData[offset + c] = dData[offset + c] + (255 - gAverage) * contrast / 255;
}else{
dData[offset + c] = dData[offset + c] - (gAverage * contrast / 255);
}
}
}else{
dData[offset] = dData[offset] + (dData[offset] - gAverage) * contrast / 255;
dData[offset + 1] = dData[offset + 1] + (dData[offset + 1] - gAverage) * contrast / 255;
dData[offset + 2] = dData[offset + 2] + (dData[offset + 2] - gAverage) * contrast / 255;
}

dData[offset + 3] = 255;
}
}
}else{
error(arguments.callee, UNSPPORT_DATA_TYPE/* {line} */);
}
return dst;
};

效果

(0)

相关推荐

  • javascript图像处理—边缘梯度计算函数

    前言 上一篇文章,我们讲解了图像处理中的膨胀和腐蚀函数,这篇文章将做边缘梯度计算函数. 图像的边缘 图像的边缘从数学上是如何表示的呢? 图像的边缘上,邻近的像素值应当显著地改变了.而在数学上,导数是表示改变快慢的一种方法.梯度值的大变预示着图像中内容的显著变化了. 用更加形象的图像来解释,假设我们有一张一维图形.下图中灰度值的"跃升"表示边缘的存在: 使用一阶微分求导我们可以更加清晰的看到边缘"跃升"的存在(这里显示为高峰值): 由此我们可以得出:边缘可以通过定位梯

  • java数字图像处理基础使用imageio写图像文件示例

    一个BufferedImage的像素数据储存在Raster中,ColorModel里面储存颜色空间,类型等信息,当前Java只支持一下三种图像格式- JPG,PNG,GIF,如何向让Java支持其它格式,首先要 完成Java中的图像读写接口,然后打成jar,加上启动参数- Xbootclasspath/pnewimageformatIO.jar即可. Java中如何读写一个图像文件,使用ImageIO对象即可.读图像文件的代码如下: 复制代码 代码如下: File file = new File

  • Javascript图像处理—为矩阵添加常用方法

    前言 上一篇文章,我们定义了矩阵,这篇文章我们来给矩阵添加一些常用方法. toString方法 toString方法通常用作将对象转成字符串描述,所以我们将这一方法定义为输出矩阵元素. 复制代码 代码如下: Mat.prototype.toString = function(){ var tempData = this.data, text = "Mat("+ this.type +") = {\n", num = this.col * this.channel;

  • javascript图像处理—仿射变换深度理解

    前言 上一篇文章,我们讲解了图像金字塔,这篇文章我们来了解仿射变换. 仿射? 任何仿射变换都可以转换成,乘以一个矩阵(线性变化),再加上一个向量(平移变化). 实际上仿射是两幅图片的变换关系. 例如我们可以通过仿射变换对图片进行:缩放.旋转.平移等操作. 一个数学问题 在解决仿射问题前,我们来做一个数学题. 如图,对于点(x1, y1),相对于原点旋转一个角度a,那么这个点到哪里了呢? 我们将坐标系变成极坐标系,则点(x1, y1)就变成了(r, β),而旋转后变成(r, α+ β). 转回直角

  • Javascript图像处理—虚拟边缘介绍及使用方法

    前言 上一篇文章,我们来给矩阵添加一些常用方法,这篇文章将讲解图像的虚拟边缘. 虚拟边缘 虚拟边缘就是按照一定映射关系,给图像添加边缘. 那么虚拟边缘有什么用呢?比如可以很容易做一个倒影的效果:  当然这只是附带效果了,虚拟边缘主要用在图像卷积运算(例如平滑操作)时候,由于卷积运算的特点,需要将图片扩大才能对边角进行卷积运算,这时候就需要对图片进行预处理,添加虚拟边缘. 说白了,就是在一些图片处理前进行预处理. 边缘类型 这里参考OpenCV相关文档的边缘描述: 复制代码 代码如下: /* Va

  • Javascript图像处理思路及实现代码

    思路 HTML5的canvas提供了getImageData接口来获取canvas中的数据,所以我们能够先用drawImage接口将图片画在canvas上然后再通过getImageData得到图片数据矩阵. 需要注意,虽然IE9开始支持了canvas接口,但是其getImageData获取的数据并不是以标准的TypedArray方式存储的,或者说IE9没有提供对WebGL Native binary data的支持,所以如果需要对IE9支持,下面的矩阵需要用Array的方式保存.虽然IE9以下版

  • Java图像处理工具类

    本工具类的功能:缩放图像.切割图像.图像类型转换.彩色转黑白.文字水印.图片水印等 复制代码 代码如下: package net.kitbox.util; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Re

  • Javascript图像处理—阈值函数实例应用

    前言 上一篇文章,我们讲解了图像处理中的亮度和对比度的变化,这篇文章我们来做一个阈值函数. 最简单的图像分割方法 阈值是最简单的图像分割方法. 比如为了从下图中分割出苹果,我们利用前景与背景的灰度差值,通过设定一个阈值,对于该像素大于这个阈值时就以黑色表示,小于便以灰色表示. 五种阈值类型 和OpenCV一样,我们将提供五种阈值类型,方便使用. 下面是原图像的波形表示,纵坐标表示像素点的灰度值大小,蓝线是阈值大小. 二进制阈值化 公式表示是: \texttt{thresh}$}{0}{other

  • Javascript图像处理—图像形态学(膨胀与腐蚀)

    前言 上一篇文章,我们讲解了图像处理中的阈值函数,这一篇文章我们来做膨胀和腐蚀函数. 膨胀与腐蚀 说概念可能很难解释,我们来看图,首先是原图: 膨胀以后会变成这样: 腐蚀以后则会变成这样: 看起来可能有些莫名其妙,明明是膨胀,为什么字反而变细了,而明明是腐蚀,为什么字反而变粗了. 实际上,所谓膨胀应该指: 较亮色块膨胀. 而所谓腐蚀应该指: 较亮色块腐蚀. 上面图里面,由于背景白色是较亮色块,所以膨胀时就把黑色较暗色块的字压扁了--相反腐蚀时,字就吸水膨胀了-- 用数学公式表示就是: 说白了就是

  • Javascript图像处理—平滑处理实现原理

    前言 上一篇文章,我们讲解了图像的虚拟边缘,这篇文章开始进行平滑(也就是模糊)处理. 基本原理 这里直接引用OpenCV 2.4+ C++ 平滑处理和OpenCV 2.4+ C++ 边缘梯度计算的相关内容: 平滑也称模糊, 是一项简单且使用频率很高的图像处理方法. 平滑处理时需要用到一个滤波器 . 最常用的滤波器是线性 滤波器,线性滤波处理的输出像素值(例如:)是输入像素值(例如:)的加权平均: 称为核 , 它仅仅是一个加权系数. 这里涉及一种叫做"卷积"的运算,那么卷积是什么呢? 卷

随机推荐