OpenCV-灰度图蒙版GrayMask

简介: OpenCV-灰度图蒙版GrayMask

需求说明

      在对图像进行处理时,经常会有这类需求:想对感兴趣区域进行掩膜处理,只操作掩膜内数据,此时需要搭配掩膜绘制功能,并在绘制过程中希望能区分掩膜区和非掩膜区;除了掩膜本身的线条以外,还希望掩膜内图像是原色,掩膜外图像的颜色进行一定调整;通常可以采用图像透明化或者色彩单通道加深的方式实现。


      比如对三通道的图像,可以将掩膜外数据的红通道数值提高,此时该部分图像就会偏红色,如下图1所示。

图1 颜色加深的蒙版效果

       但是针对灰度图,因为图像数据本身就是单通道的,就不能借用颜色通道或者透明通道了;有一个基础的办法是将非掩膜区数据同时加减某个数值,这种方法简单但有一个弊端,比如我加了50,那原图200-255之间的数值都将变为255,这样就损坏了原图的某些特征信息。为此,我们采用非线性的算法将其进行较为合理的数值调整。


      下面介绍具体实现流程。

具体流程

      1)构造非线性参数。其中n为函数输入的参数,范围在-100到100;a、b、k为算法参数,公式见下。

n = min(max(n, -100), 100);
int k = 4;
float b = n / 100.f / k;
float a = 1.0f + k * b;

      2)参照上式,对掩膜外数据进行如下处理。

float temp = pow(float(in[j]) / 255.f, 1.0f / a) * (1.0 / (1 + b));

      3)temp的数值需要进行校准,因为灰度值如果是uchar型,范围在0-255之间,校准后乘上255,即可得到算法计算的结果。

if (temp > 1.0f)
  temp = 1.0f;
if (temp < 0.0f)
  temp = 0.0f;
uchar utemp = uchar(255 * temp);
r[j] = utemp;

      4)掩膜内数值保持不变。

r[j] = in[j];

      5)输出图像,完成。

功能函数

// 灰度图蒙版
cv::Mat GrayMask(cv::Mat input, cv::Mat mask, int n)
{
  // 通道判断
  if (input.channels() != 1)
  {
    return input;
  }
  // 非线性参数
  // 当n=100时,非掩膜区呈灰色;当n=0时,非掩膜区无变化;当n=-100时,非掩膜区黑色
  // n越小,非掩膜区越暗,n越大,非掩膜区越灰
  // 目的是区分非掩膜区和掩膜区
  n = min(max(n, -100), 100);
  int k = 4;
  float b = n / 100.f / k;
  float a = 1.0f + k * b;
  // 蒙版处理
  cv::Mat result = cv::Mat::zeros(input.size(), input.type());
  for (int i = 0; i < input.rows; ++i)
  {
    uchar *m = mask.ptr<uchar>(i);
    uchar *in = input.ptr<uchar>(i);
    uchar *r = result.ptr<uchar>(i);
    for (int j = 0; j < input.cols; ++j)
    {
      if (m[j] == 0)
      {
        float temp = pow(float(in[j]) / 255.f, 1.0f / a) * (1.0 / (1 + b));
        if (temp > 1.0f)
          temp = 1.0f;
        if (temp < 0.0f)
          temp = 0.0f;
        uchar utemp = uchar(255 * temp);
        r[j] = utemp;
      }
      else {
        r[j] = in[j];
      }
    }
  }
  return result;
}

C++测试代码

#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <stdio.h>
#include <io.h>
#include <chrono> 
#include <time.h>
#include <stdio.h>
#include <direct.h>
#include <ctime>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
using namespace std;
using namespace cv;
cv::Mat GrayMask(cv::Mat input, cv::Mat mask, int n);
int main()
{
  // 读取灰度图
  cv::Mat src = imread("1.png",0);
  // 绘制掩膜
  cv::Mat mask = cv::Mat::zeros(src.size(), CV_8UC1);
  cv::circle(mask, cv::Point(src.cols / 2, src.rows / 2), 100, cv::Scalar(255), -1);
  // 灰度图蒙版
  cv::Mat result = GrayMask(src, mask, 100);
  // 结果显示
  imshow("src", src);
  imshow("result", result);
  waitKey(0);
  system("pause");
  return 0;
}
// 灰度图蒙版
cv::Mat GrayMask(cv::Mat input, cv::Mat mask, int n)
{
  // 通道判断
  if (input.channels() != 1)
  {
    return input;
  }
  // 非线性参数
  // 当n=100时,非掩膜区呈灰色;当n=0时,非掩膜区无变化;当n=-100时,非掩膜区黑色
  // n越小,非掩膜区越暗,n越大,非掩膜区越灰
  // 目的是区分非掩膜区和掩膜区
  n = min(max(n, -100), 100);
  int k = 4;
  float b = n / 100.f / k;
  float a = 1.0f + k * b;
  // 蒙版处理
  cv::Mat result = cv::Mat::zeros(input.size(), input.type());
  for (int i = 0; i < input.rows; ++i)
  {
    uchar *m = mask.ptr<uchar>(i);
    uchar *in = input.ptr<uchar>(i);
    uchar *r = result.ptr<uchar>(i);
    for (int j = 0; j < input.cols; ++j)
    {
      if (m[j] == 0)
      {
        float temp = pow(float(in[j]) / 255.f, 1.0f / a) * (1.0 / (1 + b));
        if (temp > 1.0f)
          temp = 1.0f;
        if (temp < 0.0f)
          temp = 0.0f;
        uchar utemp = uchar(255 * temp);
        r[j] = utemp;
      }
      else {
        r[j] = in[j];
      }
    }
  }
  return result;
}

测试效果

图2 原图

图3 灰度图蒙版效果

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

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

相关文章
|
1月前
|
计算机视觉 Python
Opencv学习笔记(二):如何将整个文件下的彩色图片全部转换为灰度图
使用OpenCV库将一个文件夹内的所有彩色图片批量转换为灰度图,并提供了相应的Python代码示例。
31 0
Opencv学习笔记(二):如何将整个文件下的彩色图片全部转换为灰度图
|
算法 C++
OpenCV-白平衡(灰度世界算法)
OpenCV-白平衡(灰度世界算法)
374 0
|
6月前
|
人工智能 Linux API
OpenCV这么简单为啥不学——1.1、图像处理(灰度图、模糊图片、GaussianBlur函数、提取边缘、边缘膨胀、边缘细化)
OpenCV这么简单为啥不学——1.1、图像处理(灰度图、模糊图片、GaussianBlur函数、提取边缘、边缘膨胀、边缘细化)
103 0
|
6月前
|
计算机视觉 Python
Opencv播放视频文件、将视频转换为灰度视频实战(附Python源码)
Opencv播放视频文件、将视频转换为灰度视频实战(附Python源码)
230 0
OpenCV-基于自定义色条实现灰度图上色
OpenCV-基于自定义色条实现灰度图上色
126 0
|
存储 文字识别 计算机视觉
【OpenCv】c++ 图像初级操作 | 图像灰度化
【OpenCv】c++ 图像初级操作 | 图像灰度化
262 0
|
API 计算机视觉 Python
OpenCV_07 直方图:灰度直方图+直方图均衡化
直方图是对数据进行统计的一种方法,并且将统计值组织到一系列实现定义好的 bin 当中。其中, bin 为直方图中经常用到的一个概念,可以译为 “直条” 或 “组距”,其数值是从数据中计算出的特征统计量,这些数据可以是诸如梯度、方向、色彩或任何其他特征。
195 0
|
编解码 算法 计算机视觉
Opencv 图像处理:图像基础操作与灰度转化
Opencv 图像处理:图像基础操作与灰度转化
233 0
Opencv 图像处理:图像基础操作与灰度转化
|
计算机视觉
Qt+OpenCV小项目:灰度图转换
Qt+OpenCV小项目:灰度图转换
217 0
Qt+OpenCV小项目:灰度图转换
|
计算机视觉
使用opencv读入并显示一幅彩色图像,灰度化并显示,用canny算子得到图像边缘并显示
使用opencv读入并显示一幅彩色图像,灰度化并显示,用canny算子得到图像边缘并显示
217 0
使用opencv读入并显示一幅彩色图像,灰度化并显示,用canny算子得到图像边缘并显示