图形视频

OpenCV实践(3)- 改变图像的对比度和亮度

1 目标 (1)访问像素值; (2)初始化矩阵为0; (3)学习saturate_cast做什么和它为什么有用? (4)Get some cool info about pixel transformations 2 理论 可以参考[计算机视觉:算法和应用](http://szeliski.org/Book/)一文。 3 图像处理 (1)图像处理运算就是一个函数把输入的一个或多个图像,转换为输出图像的过程; (2)图像变换可以被看成: a) 像素点的转换; b) 邻域的操作(基于域的概念); 4 像素变换 在这类转换中,每一个输出像素点仅仅依赖于相对应的输入像素点(潜在地附加一些收集的全面信息和参数)。 这类操作的例子有:亮度和对比度的调整,以及色彩校正和转换。 4.1 亮度和对比度调整 (1) 理论公式为 (2) 在这里, 和 被称为增益和偏差参数,有时候,也被认为分别控制对比度和亮度。 (3)你可以认为f(x)是输入图像的像素值,g(x)是输出图像的像素值。那么为了方便我们就可以把上面的公式写为: 在这里,i和j分别代表像素点在行和列的位置。 4.2 代码实现 #include #include #include using namespace cv; double alpha; /**< Simple contrast control */ int beta; /**< Simple brightness control */ int main( int argc, char** argv ) { /// Read image given by user Mat image = imread( argv[1] ); Mat new_image = Mat::zeros( image.

OpenGL学习脚印:伽马校正(Gamma Correction)

写在前面 由于CRT,LED等显示设备显示颜色时并非按照线性方式工作,因此我们在程序中输出的颜色,最终输出到显示器上时会产生亮度减弱的现象,这种现象在计算光照和实时渲染时对图形质量有一定影响,需要我们加以处理。本节将熟悉Gamma校正的概念,并通过点光源的示例来表现Gamma校正对图形效果的影响。本节示例代码均可以在我的github下载。 为什么需要 γ 校正 我们在图形程序中认为(1.0, 0.0,0.0)颜色应该是(0.5,0.0, 0.0)的红色强度的2倍,但是实际上在显示设备上对于输入的原始值,并不按照线性的关系来反映这个亮度差别。显示设备对于输入的原始值,按照一种非线性的方式处理,也就是说上面原始值中红色分量提高2倍时,实际处理时得到的亮度并不是成这种2倍的比例。 事实上,CRT、LED这类显示设备,对于输入的原始值,会计算一个指数函数,即: Cout=C2.2in 。这里的2.2称为 伽马系数(Gamma factor),范围一般在2.0到2.4之间,不同显示器这个系数有区别。这个关系如下图所示(来自Gamma Correction): 上面的图中间的点线,是我们图形中工作的线性颜色,当显示器接受这个线性原始值后,进行了上面的指数计算,将会输出图中下方的实线所示的非线性的颜色,亮度会降低。对于0。0和1.0两个值显示器总是原样输出,两个值之间的颜色亮度将会降低。 因此,要想最终显示器按照我们预期的输出中间的线性颜色,我们就需要执行上述指数运算的逆运算: Ccorrected=C1.0/2.2out ,这样最终输出颜色,才会是我们在图形应用中指定的颜色。 执行这个逆运算的过程,称之为伽马校正(Gamma Correction),一般的取伽马系数2.2进行校正产生的效果在大多数显示器上都比较理想,实际还可以根据显示器不同进行查询。例如上面的颜色(0.5,0.0,0.0)执行校正后的值为: (0.5,0.0,0.0)1/2.2=(0.5,0.0,0.0)0.45=(0.73,0.0,0.0) 则实际显示为: (0.73,0.0,0.0)2.2=(0.5,0.0,0.0) 也就是说要让显示器显示我们预期的 (0.5,0.0,0.0) ,我们的着色器需要输出 (0.73,0.0,0.0) 。 另外一个需要知道的事实时,大多数的图片在显示器已经被预处理过了,因此存储的颜色信息已经是伽马校正了的,我们在处理纹理时需要工作在线性的颜色空间下,因此需要对输入的图片,例如JPEG纹理进行处理,保证它在线性颜色空间下。关于实际操作,后面会介绍。 有了上面的基础,我们直观感受下,有无伽马校正,下面是绘制人面皮肤的效果图,图形对比如下(来自The Importance of Being Linear): 上面的左图中,将输入的纹理进行了线性处理,同时最终输出时进行了伽马校正;而右边的图形两个处理都没有进行,因而面部的镜面光加上漫反射光后变成了黄色,同时面部的阴影变得太暗了。 处理输入的纹理 对于输入的纹理图片,由于大多数情况下已经进行了伽马校正,因此我们要得到他们线性的颜色,必须去除这个校正,在OpenGL中提供了两种方式。 方式一是通过在构造纹理对象时,指明纹理的内部格式为sRGB或者GL_SRGB_ALPHA,SRGB就是我们所说的已经校正后的非线性颜色,当按上述方式指明时OpenGL将会自动将其转换到线性空间。 glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); 方式二是在着色器中开始使用纹理时,手动执行转换: float gamma = 2.2; vec3 diffuseColor = pow(texture(diffuse, texCoords).rgb, vec3(gamma)); 这种方式是在着色器中执行伽马变换的逆操作,相比上一种方式,显得麻烦些。 需要注意的是,对于某些类型的纹理,例如diffuse map,通常已经工作在线性空间了,这个时候就不需要指明为sRGB格式了。在指明为sRGB格式时也需要根据不同情况加以区别。 处理着色器的输出 对于着色器的输出,我们有两种方式执行伽马校正。第一种方式,即采用OpenGL提供的FBO的选项,当开启 GL_FRAMEBUFFER_SRGB选项后,随后的所有FBO绘制将自动执行校正,包括默认的FBO。 glEnable(GL_FRAMEBUFFER_SRGB); 当开启这个选项后,执行的伽马校正,通常是2.2的校正。需要注意的是,如果你使用多个FBO来完成某项操作,当需要在中间步骤中使用线性颜色空间时,就需要关闭这个选项,否则将会在错误的颜色空间上工作。一般是在最后一个FBO上操作时开启这个选项。 第二种方式是在着色器的输出中,手动进行伽马校正: vec3 result; result = pow(result, vec3(1.

OpenGL学习脚印:Blinn-Phong光照模型

写在前面 在前面基础光照部分,我们学习了Phong Shading模型,Blinn-Phong模型对Phong模型的镜面光成分进行了改进,虽然在物理上解释没有Phong好,但是能更好地模拟光照。本节代码可以在我的github下载。 本节内容整理自: 1.www.learnopengl.com 2.Blinn-Phong Model Phong不能处理的情况 我们知道,Phong模型在计算镜面光系数为: float specFactor = pow(max(dot(reflectDir, viewDir), 0.0), 32); // 32为镜面高光系数 这里的计算由反射向量和观察向量决定,当两者的夹角 θ 超过90时,截断为0.0,则没有了镜面光成分。因此Phong模型能处理的是下面的左图中( θ≤90 )的情况,而对于右图中( θ>90 )的情况则镜面光成分计算为0(来自Advanced-Lighting)。 而右图的这种情况实际上是存在的,将镜面光成分取为0,没有很好地体现实际光照情况。例如下面的图表示的是,镜面光系数为1.0,法向量为(0.0,1.0,0.0)的平面位置在-0.5,光源在原点时,观察者在(0,0,4.0)位置时,光照展示的情形: 这里我们看到,Phong的镜面光成分,在边缘时立马变暗,这种对比太明显,不符合实际情形。 为什么会产生这样一个光线明暗分明的情形? 我尝试这样推导,对此不感兴趣地可以跳过。 首先记表面位置为 fragPos=(x,−0.5,z) , 光源位置为 lightPos=(0.0,0.0,0.0) ,则光照向量为: L=−(lightPos−fragPos)=(x,−0.5,z)(light direction) 法向量为: N=(0.0,1.0,0.0)(surface normal) 根据 reflect函数的计算原理,得到反射向量为: R=L−2.0∗dot(N,L)∗N=(x,−0.5,z)−2.0∗(−0.5)∗(0.0,1.0,0.0)=(x,0.5,z)(surface reflection) 设观察点位置为 (x′,y′,z′) ,则观察向量为: V=(x′,y′,z′)−fragPos=(x′−x,y′+0.5,z′−z)(viewer direction) 那么反射向量和观察向量的点积为: dot(R,V)=(xx′−x2+0.5y′+0.25+zz′−z2)=−[(x−x′2)2+(z−z′2)2−0.25(x′2+z′2+1+2y′)] 记 δ=0.25(x′2+z′2+1+2y′) 令 0≤dot(R,V)≤1 ,得到: δ−1≤(x−x′2)2+(z−z′2)2≤δ 由此可以看出,位置在平面y=-0.5上的点,以适当位置观察时,会形成两个同心圆,在两个同心圆之间的部分则满足 0≤dot(R,V)≤1 ,这部分有镜面光,其余部分截断为0.0,立马变暗,因此有这种明暗对比。 也就是说当观察向量和反射向量超过90度,这种截断引起了明显的明暗对比,这种情形在Blinn-Phong中得到改善。 Blinn-Phong Blinn-Phong模型镜面光的计算,采用了半角向量(half-angle vector),这个向量是光照向量L和观察向量V的取中向量,如下图所示(来自Blinn-Phong Model): 计算为: H=L+V||L+V|| 当观察向量与反射向量越接近,那么半角向量与法向量N越接近,观察者看到的镜面光成分越强。 对比Phong和Blinn-Phong计算镜面光系数为:

Opencv学习之图像边缘检测

该博客只为记录点滴所学,若有误导,还请大家原谅,并不吝赐教。 一直不太明白应用函数求导的方法能求出图像强度变化的边缘,其实就是图像边缘检测。现在终于想通了,解释如下。比如一张如下的图片: 图1 检测边缘可以检测到狗和兔子的轮廓。因为它们的轮廓跟其周围的像素值强度差是很明显的。那怎样理解这个呢?我们先假设有一个一维的图片,一维的图片就是一条线。它可以如下表示: 图2 横轴表示像素坐标,纵轴表示像素值。(如果不太好理解的话,我们可以对应二维图片来理解,像素坐标就是诸如(x,y)这样的值,只不过一维图片只需一个值来表示像素坐标,这里只需用t表示。像素值是一样理解的。) 再说回上面图2那张图片,可以看到在红色圆圈处像素值跳跃比较大。即在同样的delta t区间里,该处的像素值变化最大。而此处的导数值也越大,趋于无穷。于是我们就可以将其看成是一维图像的边缘。将其延伸到二维图片,即我们所认知的看到的普通的图片,也是一样的道理。我们可以将其拆分成两个轴向的一维图片,然后组合起来。 综上,就解释了为什么求导可以得出一张图片的边缘。比如我们假设当导数超过一个限度之后,就认为它是边缘,我们就把它的像素值设为255,否则设为0.

地球实时卫星图片资源-与当前时间只相差30分钟

地球实时卫星图片资源-与当前时间只相差30分钟 在这里跟大家分享一个有趣的项目。这个项目提供一个实时地球照片源,通过向其服务器发送请求,能抓取到当前地球的照片。对于图片壁纸类的应用来说是一个不错的图片源选择。有550*550、1100*1100、2200*2200分辨率图片资源,您可以将它们集成在您的应用当中,让它成为您的应用的一个绝对亮点。 该项目的图片来自卫星实时拍摄的地球照片,更新频率为每十分钟一次,如下所示图样: 该项目不仅提供这些资源,而且还提供配套的基于HTTP网络协议的接口,同时提供全套主流语言 SDK ,如 C、C++、java、object-c 等,用户可以根据自己的开发语言,方便快捷的接入服务。同时也提供原始的HTTP协议与相关的文档和辅助开发的测试工具。 该项目的图片云服务端从性能、安全性、可扩展性为不同的应用需求提供了全套可靠的服务。 在可扩展性方面针对实时图片,该项目可以提供不同分辨率的图片,550 * 500、1100 * 1100、2200 * 2200等,并且提供裁剪、压缩、缩放、格式转换、图片效果(调整亮度、对比度)等等功能服务。 该项目提供原始无损的PNG图片,同时也支持在服务端将图片转换成JPG、BMP、webp等格式的图片。 在性能上面,该项目提供了BGP高速的云服务器,同时提供全网的CDN加速分发的功能,保证APP在任何网络下面都能够快速的获取图片。 在安全性方面,该项目以HTTP协议为基础,提供了一套安全体系,保证生成的图片URL有安全验证、有过期时间,确保不被盗链。 更多的信息请查看: 官方网站 www.runimg.com 演示图片 GMT+0 2016年4月28日00时10分00秒 http://www.runimg.com/demo_img/2016_04_28_00_10_00_4d.png GMT+0 2016年4月28日00时20分00秒 http://www.runimg.com/demo_img/2016_04_28_00_10_00_4d.png GMT+0 2016年4月28日00时30分00秒 http://www.runimg.com/demo_img/2016_04_28_00_10_00_4d.png GMT+0 2016年4月28日00时40分00秒 http://www.runimg.com/demo_img/2016_04_28_00_10_00_4d.png GMT+0 2016年4月28日12时00分00秒 http://www.runimg.com/demo_img/2016_04_28_00_10_00_4d.png GMT+0 2016年4月28日12时10分00秒 http://www.runimg.com/demo_img/2016_04_28_00_10_00_4d.png GMT+0 2016年4月28日12时20分00秒 http://www.runimg.com/demo_img/2016_04_28_00_10_00_4d.png GMT+0 2016年4月28日12时30分00秒 http://www.runimg.com/demo_img/2016_04_28_00_10_00_4d.png GMT+0 2016年4月28日12时40分00秒 http://www.runimg.com/demo_img/2016_04_28_00_10_00_4d.png 文档工具 协议文档 http://www.kancloud.cn/khvysofq/runimg/101183 辅助测试工具 http://www.runimg.com/signature.html SDK JAVA SDK https://github.com/jinjiangztc/image_download_java.git C++ SDK https://git.oschina.net/guangleihe/runimg-sdk.git Object-C SDK https://github.com/itayou/RunimgService.git

OpenGL(三)图形变换之裁剪变化

通过裁剪平面程序例子学习裁剪相关知识 #include #include #include static GLfloat xRot =0.0f; static GLfloat yRot = 0.0f; void SetupRC(void) { glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glShadeModel(GL_FLAT); //明暗模式 以最后的所填颜色填充 } void ChangeSize(int w, int h) { if (h == 0) h = 1; //设置视区尺寸 glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); //设置修剪空间 GLfloat fAspect = (float)w / (float)h; gluPerspective(60, fAspect, 1.0, 20.0f); glMatrixMode(GL_MODELVIEW); } //在窗口中绘制图形 void RenderScene(void) { //定义裁剪平面方程系数,这里平面方程为x=0; GLdouble equ[4] = { 1.0, 0.0, 0.0 ,0.

【机器视觉】光源照明方式简介

原文地址:机器视觉光源照明方式简介 机器视觉光源照明方式简介 光源是影响机器视觉系统输入的重要因素,其直接影响输入数据的质量和至少30%的应用效果。由于没有通用的机器视觉照明设备,所以针对每个特定的应用实例,要选择相应的照明装置,以达到最佳效果。下面介绍几种常见的照明方式。 一般目的的照明(直接照明):光直接射向物体,得到清楚的影像。当需要得到高对比度物体图像的时候,这种类型的光很有效。但是当用它照在光亮或反射的材料上时,会引起像镜面的反光。通用照明一般采用环状或点状照明。环灯是一种常用的通用照明方式,其很容易安装在镜头上,可给漫反射表面提供足够的照明。 暗场(Dark Field)照明:暗场照明是相对于物体表面提供低角度照明。使用相机拍摄镜子使其在其视野内,如果在视野内能看见光源就认为使亮场照明,相反的在视野中看不到光源就是暗场照明。因此光源是亮场照明还是暗场照明与光源的位置有关。典型的,暗场照明应用于对表面部分有突起的部分的照明或表面纹理变化的照明。 背光照明:从物体背面射过来均匀视场的光。通过相机可以看到物面的侧面轮廓。背光照明常用于测量物休的尺寸和定物体的方向。背光照明产生了很强的对比度。应用背光技术时候,物体表面特征可能会丢失。例如,可以应用背光技术测量硬币的直径,但是却无法判断硬币的正反面。 同轴照明:同轴光的形成即通过垂直墙壁出来的变化发散光,射到一个使光向下的分光镜上,相机从上面通过分光镜看物体。这种类型的光源对检测高反射的物体特别有帮助,还适合受周围环境产生阴影的影响,检测面积不明显的物体。 漫射照明:连续漫反射照明应用于物体表面的反射性或者表面有复杂的角度。连续漫反射照明应用半球形的均匀照明,以减小影子及镜面反射。这种照明方式对于完全组装的电路板照明非常有用。这种光源可以达到170立体角范围的均匀照明。 除了以上介绍的几种常用照明技术,还有些特殊场合所使用的照明技术,比如在线阵相机中需要亮度集中的条形光照明;比如在精密尺寸测量中与远心镜头配合使用的平行光照明技术;比如在高速在线测量中减小被测物模糊的频闪光照明技术;又比如可以主动测量相机到光源的距离结构光照明技术和减少杂光干扰的偏振照明技术等。 此外,很多复杂的被测环境需要两种或两种以上照明技术共同配合完成。因而丰富的照明技术可以解决视觉系统中图像获取的很多问题,光源照明技术的选择可能对一个视觉系统的成功与否至关重要。

全黑图像去除

本系列文章由 @yhl_leo 出品,转载请注明出处。 文章链接: http://blog.csdn.net/yhl_leo/article/details/50904358 昨天一个朋友,向我求助,帮忙去除掉一组遥感影像数据中,因为裁剪时产生的全黑图像,实现起来也很简单,就将工程代码提供给大家: GitHub链接:yhlleo/ImageFormatConversion 图像格式为单通道16-bit的tif,可以使用OpenCV库读取: cv::Mat curImage = cv::imread(fileName, IMREAD_UNCHANGED); 因为图像是16-bit的,所指使用图片查看器,浏览的话,肯定是全黑的。但是可以在Photoshop中,调整灰度曲线,显示图片内容(将曲线调成近似直角折线): 那些黑色图像(真的是全黑,像素值为0),判断方法比较简单,获取图像灰度最大最小值,区间范围是0,必然是全黑图像: double pMax = 0, pMin = 0; cv::minMaxIdx(curImage, &pMin, &pMax); int pRange = pMax - pMin; if ( pRange > 0 ) { // ... } else { // Black image // ... } 如果想把16-bit图像转为常见的8-bit图像,我使用的方法是这样的: if( pRange > 0 ) { for ( int i=0; iint pValue = ( static_cast<int>(*++data_cur & 0xffff) - ipMin ) * 255 / pRange; data_trans[i] = static_cast(pValue); } } 即,使用简单的线性拉伸方法:

PS图层样式中的“图案叠加”技巧

在我们的Photoshop中,图层样式是被应用最多的设计手段,那么在图层样式中,图案叠加相信有不少的朋友已经用过了,下面我们先来看看这图案叠加可以用来做什么~ 首先在Photoshop中随意新建个画布~填充一个自己喜欢的颜色~ 然后我们再新建个画布(参数如下) 然后我们得到一个50*50px的新画布,在该画布中我们需要隐藏掉背景图层,在这个画布中绘制一个小爱心~(摆放位置如下图所示) 然后在我的编辑菜单中找到选项卡“定义图案”~ 然后在新画布中会弹出个窗口,如下图所示,输入好名字然后点击确定~ 然后回到我们的第一块画布中,双击该画布中的黄色背景图层~ 弹出图层样式窗口->选择->“图案叠加”选项卡,得到如下图所示画面~ 可以看到我们刚刚确定保存的小爱心图案出现在这里面了,选择它,然后点击确定~ 你会发现你的画面会变成这样~ 是不是多了很多小爱心,这就如同图案的平铺效果一样,可以使用它做特殊的壁纸效果哟, 那么问题就来了!!!能不能单独把做的这个图案叠加的平铺效果拿出来?(有的童鞋可能只需要这个平铺效果,不需要背景/底色) 答案是,可以的,有两种方法 先说第一种: 选中做了图案叠加效果的图层,然后在菜单栏中的“图层”选择->“图层样式”选项卡->在该选项卡中再选择“创建图层”~ 然后你会发现你的图层~ 之前是这样 现在是这样 是不是变成了一个剪切蒙版的样子,SO… 你就可以把它单独拿出来慢慢“编辑”了; 然后,现在说第二种,也是最实用~最简单的。 要想得到独立的图案叠加背景效果,我们先新建一个图层取名“图案层”~ 然后给他填充一个颜色(随意填充)~ 然后再双击它给他添加图层样式的“图案叠加”效果~ 然后你的画布上就变成这样了~ 重点来了,接下来怎么做?先看图~ 把这个图层的填充色变为0%,像这样~ 然后见证奇迹的时刻~ 黑底没有了~ 现在总结说说第二种的好处,你可以随意更换/调节图案叠加的的图案效果(包括自己做的花纹图案,都行)~~~~妈妈再也不担心我没各种背景图案用了……

泊松融合

拖拖拉拉快一个月了 这是探索出来的 但感觉效果不是特别好 我目前只能做到这样子了:想把左图的人放进右图的水池中 用泊松融合想实现无缝自然的效果: 左图是直接做mask镶嵌的结果 右图是解了泊松方程后的最终的结果 我所能得到的: 感觉效果不够好 因为这个理想结果是这样: 看这个就比我的自然很多很多 我的应该是有问题的 但我是按照步骤来的 目前不知道错在哪里 在找:[今天经过网友的提醒,找到了,原来是迭代次数问题,我这个效果是只迭代一次的,再迭代几次就能达到理想效果,那篇论文中没有提过这个迭代!害死我了] A=imread(‘F:\fisheye\pond.jpg’); src=A; [ma,na,ka]=size(A); dst=imread(‘F:\fisheye\swim.jpg’); se=strel(‘diamond’,10); B_erode=imerode(dst,se); Berodelogical=im2bw(B_erode); imshow(Berodelogical) B=dst; [mb,nb,kb]=size(B); >> for i=1:mb for j=1:nb if(Berodelogical(i,j)==1) Berodelogical(i,j)=0; else Berodelogical(i,j)=1; end end end dstX=100; dstY=100; for i=dstY:dstY+mb-1 for j=dstX:dstX+nb-1 ii=i-(dstY-1); jj=j-(dstX-1); if(Berodelogical(ii,jj)==1) A(i,j,1)=B(ii,jj,1); A(i,j,2)=B(ii,jj,2); A(i,j,3)=B(ii,jj,3); end end end ROI=uint8(zeros(mb,nb,3)); for i=dstY:dstY+mb-1 for j=dstX:dstX+nb-1 ii=i-(dstY-1); jj=j-(dstX-1); ROI(ii,jj,1)=A(i,j,1); ROI(ii,jj,2)=A(i,j,2); ROI(ii,jj,3)=A(i,j,3); end end w=[0,-1,1]; ROIgradienty=imfilter(double(ROI),w,’conv’); ROIgradientx=imfilter(double(ROI),w’,’conv’); %接下来对梯度求偏导得到融合图像的散度 lap