目录

实现原理

代码实现

结果


实现原理

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

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

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

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

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;// 边缘平滑过渡
Mat midrate = Mat::zeros(input.size(), CV_32FC1);
Mat brightrate = 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起到了很好的过渡作用。

// 高光提亮,获取结果图
Mat result = 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;}}
}

代码实现

function.h

#pragma once
#include <iostream>
#include <opencv2/highgui.hpp>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;Mat HighLight(Mat input, int light);

function.cpp

#include "function.h"// 图像高光选取
Mat HighLight(Mat input, int light)
{// 生成灰度图Mat gray = Mat::zeros(input.size(), CV_32FC1);Mat f = input.clone();f.convertTo(f, CV_32FC3);vector<Mat> pics;split(f, pics);gray = 0.299f * pics[2] + 0.587 * pics[2] + 0.114 * pics[0];gray = gray / 255.f;// 确定高光区Mat thresh = Mat::zeros(gray.size(), gray.type());thresh = gray.mul(gray);// 取平均值作为阈值Scalar t = mean(thresh);Mat mask = 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;// 边缘平滑过渡Mat midrate = Mat::zeros(input.size(), CV_32FC1);Mat brightrate = 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;}}}// 高光提亮,获取结果图Mat result = 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;
}

main.cpp

#include <iostream>
#include <opencv2/highgui.hpp>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/opencv.hpp>
#include "function.h"
using namespace cv;
using namespace std;int main()
{Mat scr = imread("F:\\picture\\江.jpg");Mat res = HighLight(scr, -50);imshow("原图", scr);imshow("处理后", res);waitKey(0);return 0;
}

结果

原图像
light为50
light为-50

如果以上内容对你有所帮助,不妨点赞关注一下,感谢观看!

OpenCV图像高光相关推荐

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

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

  2. OpenCV图像梯度(Sobel和Scharr)

    OpenCV图像梯度(Sobel和Scharr) 1 图像梯度是什么? 2 图像梯度的用途 3 图像梯度的使用 参考 这篇博客将介绍图像渐变以及如何使用OpenCV的cv2.Sobel计算Sobel渐 ...

  3. Python,OpenCV图像金字塔cv2.pyrUp(), cv2.pyrDown()

    Python,OpenCV图像金字塔cv2.pyrUp, cv2.pyrDown 1. 效果图 2. 原理 2.1 什么是图像金字塔 2.2 金字塔分类 2.3 应用 3. 源码 参考 这篇博客将介绍 ...

  4. OpenCV图像缩放插值之BiCubic双三次插值

    图像缩放算法简介 在图像的仿射变换中,很多地方需要用到插值运算,常见的插值运算包括最邻近插值,双线性插值,双三次插值(立体插值),兰索思插值等方法,OpenCV提供了很多方法,其中,双线性插值由于折中 ...

  5. python皮同_Python OpenCV 图像的双线性插值算法,全网最细致的算法说明_橡皮擦,一个逗趣的互联网高级网虫-CSDN博客...

    原文作者:梦想橡皮擦 原文标题:Python OpenCV 图像的双线性插值算法,全网最细致的算法说明 发布时间:2021-02-17 20:55:32 Python OpenCV 365 天学习计划 ...

  6. OpenCV 图像加载和显示

    OpenCV 图像加载和显示 OpenCV 图像加载和显示 加载图像(使用cv :: imread) 创建一个名为OpenCV的窗口(使用cv :: namedWindow) 在OpenCV窗口中显示 ...

  7. OpenCV图像坐标系与行列宽高的关系

    这篇文章挺好    OpenCV图像坐标系与行列宽高的关系 图片坐标系,与从小到大见到的xy坐标系,x轴方向相同,只是y轴方向相反.

  8. python使用openCV图像加载(转化为灰度图像)、Canny边缘检测器检测图像的边缘(Detect Edges)

    python使用openCV图像加载(转化为灰度图像).Canny边缘检测器检测图像的边缘(Detect Edges) 目录

  9. python使用openCV图像加载(转化为灰度图像)、使用filter2D函数对图像进行锐化(Sharpen Images)

    python使用openCV图像加载(转化为灰度图像).使用filter2D函数对图像进行锐化(Sharpen Images) 目录

最新文章

  1. 更改windows域名
  2. java script 技巧
  3. vue router html后缀,vue-router.html
  4. 对称加密算法之分组加密的六种工作模式(ECB、CBC、PCBC、CFB、OFB、CTR)
  5. pack unpack 用法 转载
  6. linux su命令位置,Linux命令大全su详解
  7. 5 Tips for creating good code every day; or how to become a good software developer
  8. -Xms -Xmx -Xmn -Xss 核心总结
  9. 计算机连接未识别的网络,电脑网络连接出现未识别的网络怎么办
  10. 程序员必备的量子力学知识
  11. 虚拟服务器 共享打印机,教你轻松解决打印机共享难题
  12. I/Q数据频谱分析仪简介
  13. linux12k8s --> 03二进制安装
  14. 投资与财报的学习笔记
  15. mysql 数字中文混排序
  16. 港科夜闻|香港科大张利民教授荣获2023年度美国土木工程师学会派克奖(Ralph B. Peck Award)...
  17. PHP中的empty()函数
  18. S君 被父母毁掉的一生 r瓴
  19. Access denied for user ''@'localhost' (using password: NO)之idea坑~
  20. 几年前你错过了淘宝错过了微商,今天的亚马逊你还要错过吗?

热门文章

  1. 搜索 dfs+bfs
  2. 「助记词密盒」用户协议与隐私政策
  3. 在线通过dd命令备份分区
  4. 在github上部署静态页面
  5. 《火车头采集器采集网页数据》火车头配置规则采集信息文章数据。
  6. windows平台基础工作软件整理【持续更新】
  7. Dubbo源码分析(三) -- Dubbo的服务发现源码深入解析4万字长文
  8. 【UML】UML建模
  9. 【231】罗技优联接收器配对使用方法
  10. windows键盘按键输入错乱;