2017-05-07 17:13:49 u013085897 阅读数 7665

       图像处理中,图像亮度调节可能是最简单的算法了,非常常见的线性运算即可完成亮度调节,比如所有像素点亮度值乘或者加一个增强系数,使得图像整体变亮或者变暗。看过一些相关开源代码,常见的操作是乘以一个亮度调节系数。但是,这样做很容易使图像出现过饱和现象,即亮度值超出255。photoshop中是如何实现的不得而知,每个版本可能也不一样。还是说说我的实现方法,其实就是在调节过程中,根据像素点亮度,做非线性调节,即高光、阴影部分调节小一点,中间部分多调节一些,这样亮度调节看着更自然一些。下面是示例代码:

void ImageBrightness(BMPINFO *pSrcBitmap, float strength)
{
	int brightness = (int)(strength*100);
	uchar lookupTable[256];
	for (int i = 0; i < 256; i++)
	{
		lookupTable[i] = (uchar)MIN(255, MAX(0, i + sin(FILTER_PI*i / 255.0f)*brightness));
	}

	int size = pSrcBitmap->lWidth*pSrcBitmap->lHeight;
	uchar* pSrcData = pSrcBitmap->pPlane[0];
	for (int i = 0; i < size; i++, pSrcData+=4)
	{
		pSrcData[AXJ_BLUE] = lookupTable[pSrcData[AXJ_BLUE]];
		pSrcData[AXJ_GREEN] = lookupTable[pSrcData[AXJ_GREEN]];
		pSrcData[AXJ_RED] = lookupTable[pSrcData[AXJ_RED]];
	}
}

       亮度调节示例图片,上面为原图,下面为结果图。

              

              




2017-05-25 09:37:58 u010554381 阅读数 1549


http://blog.csdn.net/lichengyu/article/details/20840135

本质上是关于灰度的一个幂函数,当系数gamma大于1时,低灰度值的动态范围减小,高灰度值的动态范围增大,整体的灰度值减小;gamma小于1时则相反;

人眼是遵循gamma小于1曲线对输入图像进行处理,其他方面更多应用于渲染,此处不做描述!


2019-01-17 17:14:03 qq_34814092 阅读数 775

Java OpenCV-4.0.0 图像处理09 图像混合以及亮度与对比度的调节

Java OpenCV-4.0.0 图像混合以及亮度与对比度操作

图像混合 g(x)=(1-α) f_0 (x)+αf_1 (x) α(0~1)

图像亮度与对比度 g(i,j)=αf(i,j)+β其中α>α"," β是增益变量

package com.xu.opencv;

import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;

/**  
 * 
 * @Title: Image.java   
 * @Description: OpenCV-4.0.0 测试文件
 * @Package com.xu.test   
 * @author: xuhyacinth     
 * @date: 2019年5月7日12:13:13   
 * @version: V-1.0.0 
 * @Copyright: 2019 xuhyacinth
 *
 */
public class Image {

	static {
		//在使用OpenCV前必须加载Core.NATIVE_LIBRARY_NAME类,否则会报错
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
	}

	public static void main(String[] args) {
		light();
	}

	/**
	 * OpenCV-4.0.0 图像混合
	 * @return: void  
	 * @date: 2019年5月7日12:16:55
	 */
	public static void addWeighted() {
		Mat src1 = Imgcodecs.imread("C:\\Users\\Administrator\\Pictures\\test01.png");
		Mat src2 = Imgcodecs.imread("C:\\Users\\Administrator\\Pictures\\test02.png");
		Mat image = new Mat(src1.size(), src1.type());
		double alpha = 0.5;
		Core.addWeighted(src1, 1 - alpha, src2, alpha, 0.0, image);
		HighGui.imshow("图像混合", image);
		HighGui.waitKey(1);
	}

	/**
	 * OpenCV-4.0.0 图像亮度和对比度调节 
	 * @return: void  
	 * @date: 2019年5月7日12:16:55
	 */
	public static void light(){
		Mat src = Imgcodecs.imread("C:\\Users\\Administrator\\Pictures\\3.jpeg");
		Mat dst = new Mat(src.size(), src.type());
		int channels = src.channels();//获取图像通道数
		double[] pixel = new double[3];
		float alpha=1.2f;
		float bate=30f;
		for (int i = 0, rlen = src.rows(); i < rlen; i++) {
			for (int j = 0, clen = src.cols(); j < clen; j++) {
				if (channels == 3) {//1 图片为3通道即平常的(R,G,B)
					pixel = src.get(i, j).clone();
					pixel[0] = pixel[0]*alpha+bate;//R
					pixel[1] = pixel[1]*alpha+bate;//G
					pixel[2] = pixel[2]*alpha+bate;//B
					dst.put(i, j, pixel);
				} else {//2 图片为单通道即灰度图
					pixel=src.get(i, j).clone();
					dst.put(i, j, pixel[0]*alpha+bate);
				}
			}
		}
		HighGui.imshow("图像亮度和对比度调节", dst);
		HighGui.waitKey(1);
	}

}



OpenCV-4.0.0 图像混合
OpenCV-4.0.0 图像亮度和对比度调节

2019-09-05 15:45:11 botao_li 阅读数 192

亮度及对比度调节

亮度及对比度需要根据数值配合一齐调节,以达到更新的视觉效果。

如果是 RGB 彩色图像,亮度与对比度调节需要在所有颜色通道上进行相同的调节。

设当前像素点位宽为 8,则像素值范围 0~255。

设当前像素点值为 x,调节输出像素点值为 y。

设亮度参数b范围 -1~1,则有亮度调节公式:
yb=x+255×by={0yb0255yb255yb0&lt;yb&lt;255 yb=x+255\times b\\ y=\begin{cases} 0&amp;yb\leq0\\ 255&amp;yb\geq255\\ yb&amp;0&lt;yb&lt;255 \end{cases}
设对比度参数c范围 -1~1,对比度门限 th,则有对比度调节公式:
yc={xth?255:0c=1x+(xth)×(11c1)0c&lt;1x+(xth)×cc&lt;0y={0yc0255yc255yb0&lt;yc&lt;255 yc=\begin{cases} x\geq th? 255:0&amp;c=1\\ x+(x-th)\times(\frac{1}{1-c}-1)&amp;0\leq c&lt;1\\ x+(x-th)\times c&amp;c&lt;0 \end{cases}\\ y=\begin{cases} 0&amp;yc\leq0\\ 255&amp;yc\geq255\\ yb&amp;0&lt;yc&lt;255 \end{cases}
前述公式仅用于亮度或者对比度单独调节的情况,实际情况下需要将亮度对比度一同调节,并且在对比度数值大于 0 的情况下先调节亮度,在对比度数值小于 0 的情况下先调整对比度

在 FPGA 实现中,将亮度参数 b 定义为 16 位有符号整数,用补码表示(整字节数定义,方便外部配置参数值),数值范围 -255 至 255,单独计算亮度的方法:
y=x+b y=x+b
计算结果再经过 0 至 255 范围的饱和控制,得到亮度调节的结果。

将对比度参数 c 定义为 16 位有符号整数,用补码表示,范围 -255 至 255,单独计算对比度的方法:
y={x128?255:0c=255x+(x128)×c255c0c&lt;255x+(x128)×c255c&lt;0 y=\begin{cases} x\geq 128?255:0&amp;c=255\\ x+(x-128)\times\frac{c}{255-c}&amp;0\leq c&lt;255\\ x+(x-128)\times \frac{c}{255}&amp;c&lt;0 \end{cases}
计算结果再经过 0 至 255 范围的饱和控制,得到对比度调节的结果。

由于亮度及对比度调节需要根据对比度参数选择不同的先后顺序,因此 FPGA 计算时分为两条计算流水线,完成计算后再根据对比度参数选择对应的计算流水线的输出。

对比度参数 c 值大于等于 0 的计算流水线:

在这里插入图片描述

sysgen 中的实现如下:

在这里插入图片描述

注意上图中橙色背景的除法计算,Divide 模块的配置如下:

在这里插入图片描述

注意在 Divide 输入数据需要用 Convert 模块先由有符号整数补码转为浮点数,并且需要将 Divide 输出由 Convert 模块将浮点数转为有符号整数补码。

最后输出之前用于饱和控制的 Convert 模块的配置如下,注意 Overflow 配置为 Saturate:

在这里插入图片描述

对比度参数 c 值小于 0 的计算流水线:

在这里插入图片描述

sysgen 中的实现如下:

在这里插入图片描述

注意上图中用截去低 8 位的方法近似实现除以 255 的计算,以节约计算资源。

最终由对比度参数值通过 Mux 模块选择计算流的输出:

在这里插入图片描述

仿真结果。

试验图片来源于:https://unsplash.com/

输入原始图像:

在这里插入图片描述

输出图像,亮度参数 50,对比度参数 100:

在这里插入图片描述

输出图像,亮度参数 -10,对比度参数 -50:

在这里插入图片描述

2018-08-08 13:01:13 u012366767 阅读数 866

    WPF图像处理程序,包括亮度、饱和度、对比度、Gamma调节。

 

// Lightness Adjust
        public static void BitmapLightnessAdjust(Bitmap curBitmap, int width, int height, int delta)
        {
            if (delta == 0)
            {
                return;
            }
            Rectangle rect = new Rectangle(0, 0, width, height);
            BitmapData bmpData = curBitmap.LockBits(rect, ImageLockMode.ReadWrite, curBitmap.PixelFormat);
            IntPtr ptr = bmpData.Scan0;
            int bytes = width * height * 4;
            byte[] rgbValues = new byte[bytes];
            Marshal.Copy(ptr, rgbValues, 0, bytes);
            if (delta > 0)
            {
                for (int i = 0; i < rgbValues.Length; i = i + 4)
                {
                    rgbValues[i] = (byte)Math.Min(255, rgbValues[i] + delta);
                    rgbValues[i + 1] = (byte)Math.Min(255, rgbValues[i + 1] + delta);
                    rgbValues[i + 2] = (byte)Math.Min(255, rgbValues[i + 2] + delta);
                }
            }
            else
            {
                for (int i = 0; i < rgbValues.Length; i = i + 4)
                {
                    rgbValues[i] = (byte)Math.Max(0, rgbValues[i] + delta);
                    rgbValues[i + 1] = (byte)Math.Max(0, rgbValues[i + 1] + delta);
                    rgbValues[i + 2] = (byte)Math.Max(0, rgbValues[i + 2] + delta);
                }
            }
            Marshal.Copy(rgbValues, 0, ptr, bytes);
            curBitmap.UnlockBits(bmpData);
        }

        // Saturation Adjust
        public static void BitmapSaturationAdjust(Bitmap curBitmap, int width, int height, int delta)
        {
            if (delta == 0)
            {
                return;
            }
            Rectangle rect = new Rectangle(0, 0, width, height);
            BitmapData bmpData = curBitmap.LockBits(rect, ImageLockMode.ReadWrite, curBitmap.PixelFormat);
            IntPtr ptr = bmpData.Scan0;
            int bytes = width * height * 4;
            byte[] rgbValues = new byte[bytes];
            Marshal.Copy(ptr, rgbValues, 0, bytes);
            for (int i = 0; i < rgbValues.Length; i = i + 4)
            {
                if (rgbValues[i] > 128)
                {
                    rgbValues[i] = (byte)Math.Min(255, rgbValues[i] + delta);
                }
                else
                {
                    rgbValues[i] = (byte)Math.Max(0, rgbValues[i] - delta);
                }
                if (rgbValues[i + 1] > 128)
                {
                    rgbValues[i + 1] = (byte)Math.Min(255, rgbValues[i + 1] + delta);
                }
                else
                {
                    rgbValues[i + 1] = (byte)Math.Max(0, rgbValues[i + 1] - delta);
                }
                if (rgbValues[i + 2] > 128)
                {
                    rgbValues[i + 2] = (byte)Math.Min(255, rgbValues[i + 2] + delta);
                }
                else
                {
                    rgbValues[i + 2] = (byte)Math.Max(0, rgbValues[i + 2] - delta);
                }
            }
            Marshal.Copy(rgbValues, 0, ptr, bytes);
            curBitmap.UnlockBits(bmpData);
        }

        // Contrast Adjust
        public static void BitmapContrastAdjust(Bitmap curBitmap, int width, int height, int delta)
        {
            if (delta == 0)
            {
                return;
            }
            Rectangle rect = new Rectangle(0, 0, width, height);
            BitmapData bmpData = curBitmap.LockBits(rect, ImageLockMode.ReadWrite, curBitmap.PixelFormat);
            IntPtr ptr = bmpData.Scan0;
            int bytes = width * height * 4;
            byte[] rgbValues = new byte[bytes];
            Marshal.Copy(ptr, rgbValues, 0, bytes);
            if (delta > 0)
            {
                for (int i = 0; i < rgbValues.Length; i = i + 4)
                {
                    if (rgbValues[i] > 128 && rgbValues[i + 1] > 128 && rgbValues[i + 2] > 128)
                    {
                        rgbValues[i] = (byte)Math.Min(255, rgbValues[i] + delta);
                        rgbValues[i + 1] = (byte)Math.Min(255, rgbValues[i + 1] + delta);
                        rgbValues[i + 2] = (byte)Math.Min(255, rgbValues[i + 2] + delta);
                    }
                    if (rgbValues[i] < 128 && rgbValues[i + 1] < 128 && rgbValues[i + 2] < 128)
                    {
                        rgbValues[i] = (byte)Math.Max(0, rgbValues[i] - delta);
                        rgbValues[i + 1] = (byte)Math.Max(0, rgbValues[i + 1] - delta);
                        rgbValues[i + 2] = (byte)Math.Max(0, rgbValues[i + 2] - delta);
                    }
                }
            }
            else
            {
                for (int i = 0; i < rgbValues.Length; i = i + 4)
                {
                    if (rgbValues[i] > 128 && rgbValues[i + 1] > 128 && rgbValues[i + 2] > 128)
                    {
                        rgbValues[i] = (byte)Math.Max(128, rgbValues[i] + delta);
                        rgbValues[i + 1] = (byte)Math.Max(128, rgbValues[i + 1] + delta);
                        rgbValues[i + 2] = (byte)Math.Max(128, rgbValues[i + 2] + delta);
                    }
                    if (rgbValues[i] < 128 && rgbValues[i + 1] < 128 && rgbValues[i + 2] < 128)
                    {
                        rgbValues[i] = (byte)Math.Min(128, rgbValues[i] - delta);
                        rgbValues[i + 1] = (byte)Math.Min(128, rgbValues[i + 1] - delta);
                        rgbValues[i + 2] = (byte)Math.Min(128, rgbValues[i + 2] - delta);
                    }
                }
            }
            Marshal.Copy(rgbValues, 0, ptr, bytes);
            curBitmap.UnlockBits(bmpData);
        }

        // Gamma Adjust
        public static void BitmapGammaAdjust(Bitmap curBitmap, int width, int height, double delta)
        {
            if (delta == 1)
            {
                return;
            }
            Rectangle rect = new Rectangle(0, 0, width, height);
            BitmapData bmpData = curBitmap.LockBits(rect, ImageLockMode.ReadWrite, curBitmap.PixelFormat);
            IntPtr ptr = bmpData.Scan0;
            int bytes = width * height * 4;
            byte[] rgbValues = new byte[bytes];
            Marshal.Copy(ptr, rgbValues, 0, bytes);
            for (int i = 0; i < rgbValues.Length; i = i + 4)
            {
                rgbValues[i] = (byte)Math.Min(255, (int)Math.Round(255 * Math.Pow(rgbValues[i] / 255.0, delta)));
                rgbValues[i + 1] = (byte)Math.Min(255, (int)Math.Round(255 * Math.Pow(rgbValues[i + 1] / 255.0, delta)));
                rgbValues[i + 2] = (byte)Math.Min(255, (int)Math.Round(255 * Math.Pow(rgbValues[i + 1] / 255.0, delta)));
            }
            Marshal.Copy(rgbValues, 0, ptr, bytes);
            curBitmap.UnlockBits(bmpData);
        }

 

没有更多推荐了,返回首页