作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

实现原理

PS中的高光命令是一种校正由于太接近相机闪光灯而有些发白的焦点的方法。在用其他方式采光的图像中,这种调整也可用于使高光区域变暗。要实现图像的高光调整,首先要识别出高光区;再通过对高光区的色彩进行一定变换,使其达到提光或者暗化效果;最后也是最重要的,就是对高光区和非高光区的边缘作平滑处理。

下方介绍具体流程。

具体流程

1)读取识别图像的原图,并转灰度图,再归一化。

// 生成灰度图
cv::Mat gray = cv::Mat::zeros(input.size(), CV_32FC1);
cv::Mat f = input.clone();
f.convertTo(f, CV_32FC3);
vector<cv::Mat> pics;
split(f, pics);
gray = 0.299f*pics[2] + 0.587*pics[2] + 0.114*pics[0];
gray = gray / 255.f;

图1 灰度图

2)确定高光区。因为我们要识别高光,所以thresh通过gray*gray,得到的图像中原本亮的地方则为亮,取平均值当阈值,进行二值化得到掩膜mask。

// 确定高光区
cv::Mat thresh = cv::Mat::zeros(gray.size(), gray.type());
thresh = gray.mul(gray);
// 取平均值作为阈值
Scalar t = mean(thresh);
cv::Mat mask = cv::Mat::zeros(gray.size(), CV_8UC1);
mask.setTo(255, thresh >= t[0]);

图2 掩膜图

3)对掩膜区边缘进行平滑过渡。假设light为50,那么midrate的掩膜区值为1.5,黑色区为1,过渡区为1~1.5;bright的掩膜区为0.125,黑色区为0,过渡区为0~0.125。

// 参数设置
int max = 4;
float bright = light / 100.0f / max;
float mid = 1.0f + max * bright;// 边缘平滑过渡
cv::Mat midrate = cv::Mat::zeros(input.size(), CV_32FC1);
cv::Mat brightrate = cv::Mat::zeros(input.size(), CV_32FC1);
for (int i = 0; i < input.rows; ++i)
{uchar *m = mask.ptr<uchar>(i);float *th = thresh.ptr<float>(i);float *mi = midrate.ptr<float>(i);float *br = brightrate.ptr<float>(i);for (int j = 0; j < input.cols; ++j){if (m[j] == 255){mi[j] = mid;br[j] = bright;}else {mi[j] = (mid - 1.0f) / t[0] * th[j] + 1.0f;br[j] = (1.0f / t[0] * th[j])*bright;}}
}

4)根据midrate和brightrate,进行高光区提亮。对非高光区而言,midrate都为1,brightrate都为0,即没有变化;对高光区而言,midrate都为1.5,brightrate都为0.125,所以色彩数值均有所增加,带来了提亮效果;对边缘地区,midrate和brightrate起到了很好的过渡作用。

注意:temp要进行数值限制,假设temp大于1,则进行uchar处理后数值会因为类型原因产生突变,那么图像也就变成了五颜六色。

// 高光提亮,获取结果图
cv::Mat result = cv::Mat::zeros(input.size(), input.type());
for (int i = 0; i < input.rows; ++i)
{float *mi = midrate.ptr<float>(i);float *br = brightrate.ptr<float>(i);uchar *in = input.ptr<uchar>(i);uchar *r = result.ptr<uchar>(i);for (int j = 0; j < input.cols; ++j){for (int k = 0; k < 3; ++k){float temp = pow(float(in[3 * j + k]) / 255.f, 1.0f / mi[j])*(1.0 / (1 - br[j]));if (temp > 1.0f)temp = 1.0f;if (temp < 0.0f)temp = 0.0f;uchar utemp = uchar(255*temp);r[3 * j + k] = utemp;}}
}

C++测试代码

#include <iostream>
#include <opencv2/opencv.hpp>using namespace std;
using namespace cv;cv::Mat HighLight(cv::Mat input, int light);int main()
{cv::Mat src = imread("test3.jpg");int light1 = 50;int light2 = -50;cv::Mat result1 = HighLight(src, light1);cv::Mat result2 = HighLight(src, light2);imshow("original", src);imshow("result1", result1);imshow("result2", result2);waitKey(0);return 0;
}// 图像高光选取
cv::Mat HighLight(cv::Mat input, int light)
{// 生成灰度图cv::Mat gray = cv::Mat::zeros(input.size(), CV_32FC1);cv::Mat f = input.clone();f.convertTo(f, CV_32FC3);vector<cv::Mat> pics;split(f, pics);gray = 0.299f*pics[2] + 0.587*pics[2] + 0.114*pics[0];gray = gray / 255.f;// 确定高光区cv::Mat thresh = cv::Mat::zeros(gray.size(), gray.type());thresh = gray.mul(gray);// 取平均值作为阈值Scalar t = mean(thresh);cv::Mat mask = cv::Mat::zeros(gray.size(), CV_8UC1);mask.setTo(255, thresh >= t[0]);// 参数设置int max = 4;float bright = light / 100.0f / max;float mid = 1.0f + max * bright;// 边缘平滑过渡cv::Mat midrate = cv::Mat::zeros(input.size(), CV_32FC1);cv::Mat brightrate = cv::Mat::zeros(input.size(), CV_32FC1);for (int i = 0; i < input.rows; ++i){uchar *m = mask.ptr<uchar>(i);float *th = thresh.ptr<float>(i);float *mi = midrate.ptr<float>(i);float *br = brightrate.ptr<float>(i);for (int j = 0; j < input.cols; ++j){if (m[j] == 255){mi[j] = mid;br[j] = bright;}else {mi[j] = (mid - 1.0f) / t[0] * th[j] + 1.0f;br[j] = (1.0f / t[0] * th[j])*bright;}}}// 高光提亮,获取结果图cv::Mat result = cv::Mat::zeros(input.size(), input.type());for (int i = 0; i < input.rows; ++i){float *mi = midrate.ptr<float>(i);float *br = brightrate.ptr<float>(i);uchar *in = input.ptr<uchar>(i);uchar *r = result.ptr<uchar>(i);for (int j = 0; j < input.cols; ++j){for (int k = 0; k < 3; ++k){float temp = pow(float(in[3 * j + k]) / 255.f, 1.0f / mi[j])*(1.0 / (1 - br[j]));if (temp > 1.0f)temp = 1.0f;if (temp < 0.0f)temp = 0.0f;uchar utemp = uchar(255*temp);r[3 * j + k] = utemp;}}}return result;
}

测试效果

图1 原图

图2 light为50的效果图

图3 light为-50的效果图

从测试效果中可以看出,高光区随light变化而产生亮度变化,当light为正值时,高光区有明显提亮效果;反之,则变更暗。

如果函数有什么可以改进完善的地方,非常欢迎大家指出,一同进步何乐而不为呢~

如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!

OpenCV-图像高光调整相关推荐

  1. OpenCV图像高光

    目录 实现原理 代码实现 结果 实现原理 1)读取识别图像的原图,并转灰度图,再归一化. // 生成灰度图 Mat gray = Mat::zeros(input.size(), CV_32FC1); ...

  2. Python+Opencv图像处理新手入门教程(二):颜色空间转换,图像大小调整,灰度直方图

    一步一步来吧 上一节:Python+Opencv图像处理新手入门教程(一):介绍,安装与起步 1.什么是图像 对于计算机而言,图像的本质是一个由像素点构成的矩阵. 例如我们用肉眼很容易分辨一辆汽车的后 ...

  3. Opencv图像的亮度和对比度调整

    文章目录 前言 一.图像亮度和对比度的基本概念: 1.图像亮度: 2.图像对比度: 二.RGB三通道色彩空间的图像变换: 1.线性变换公式如下: 2.操作简介: 3.图像亮度调整: 4.图像对比度调整 ...

  4. OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔总结

    我们经常会将某种尺寸的图像转换为其他尺寸的图像,如果放大或者缩小图片的尺寸,笼统来说的话,可以使用OpenCV为我们提供的如下两种方式: <1> resize函数.这是最直接的方式, &l ...

  5. 发现你的身形——OpenCV图像轮廓

    文章目录 写在最前 轮廓发现算法 边缘检测 写在最后 写在最前 我的意思不是说你长得很胖,emmmm,而是你的轮廓很大. --五星上将詹姆斯下士如是说 果然有图没图,理解是不一样的,这就体现了计算机视 ...

  6. 转载:矩阵的掩膜操作实现图像对比度调整

    矩阵的掩膜操作实现图像对比度调整 hb707934728 2017-07-04 13:54:17 1170 收藏 最后发布:2017-07-04 13:54:17首发:2017-07-04 13:54 ...

  7. OpenCV图像仿射变换

    OpenCV图像的旋转是通过图像的仿射变换来实现的,实现图像的旋转,分为三个步骤: 第一步:确定旋转角度和旋转中心. 第二步:确定旋转矩阵.通过getRotationMatrix2D函数计算出. 第三 ...

  8. python打出由边框包围的_python opencv 图像边框(填充)添加及图像混合的实现方法(末尾实现类似幻灯片渐变的效果)...

    图像边框的实现 图像边框设计的主要函数 cv.copyMakeBorder()--实现边框填充 主要参数如下: 参数一:源图像--如:读取的img 参数二--参数五分别是:上下左右边的宽度--单位:像 ...

  9. 【OpenCV新手教程之十三】OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放...

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/26157633 作者:毛星云(浅墨) ...

最新文章

  1. controller不跳转页面的几个原因_狗狗为什么不睡觉?是这几个原因
  2. 【Linux】类Unix 操作系统进程监控控制工具 Supervisor
  3. 我们是如何解决复杂系统扩展性问题的
  4. 深度学习系列之CNN核心内容
  5. 英特尔将Nervana技术融入产品路线图
  6. 一个商场营销经理的实习总结
  7. wxWidgets:wxBitmapButton类用法
  8. C++ const成员和引用成员
  9. 不知道为什么IList.Contains()总是返回FALSE
  10. python canny函数_python库skimage 应用canny边缘探测算法
  11. cookie注入原理详解(一)
  12. 初学者PLC程序及有效学习方法
  13. java运行环境安装步骤_安装JAVA运行环境步骤
  14. python新浪微博爬虫_基于Python的新浪微博数据爬虫
  15. java调用soap接口_java远程调用soap协议接口
  16. Unity3D方向键控制人物移动的代码
  17. 除了搜岛国老师的作品,以图搜图还有什么骚操作?
  18. 贪心科技NLP实习面试
  19. 糖果游戏(齐大第十一届校赛)
  20. freeCAD学习笔记二:复制与放置多个相似的实体

热门文章

  1. 时下几款著名的游戏引擎介绍,也许你只听说过“虚幻引擎”
  2. node-sass是什么?
  3. 【exp】virtualbox 安装增强功能失败问题解决(vbox虚拟机, Ubuntu)
  4. QWebEngineView如何忽略SSL证书错误
  5. 阿里云视频点播服务(上传,删除,获取播放地址,获取播放凭证)
  6. 不用计算机怎么算根号二,根号怎么打 根号2或3等于多少?
  7. 鸿蒙系统投影仪,投影仪有系统和无系统的区别 当贝OS好在哪里?体验完明白了!...
  8. 【MDS多维尺度分析】
  9. 我们“看到”的物联网,未来真正走向领域是这些方面....
  10. 广告主流量主怎么申请(微信)