C++ OpenCV实现灰度图蒙版GrayMask的示例代码

目录
  • 需求说明
  • 具体流程
  • 功能函数
  • C++测试代码
  • 测试效果

需求说明

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

比如对三通道的图像,可以将掩膜外数据的红通道数值提高,此时该部分图像就会偏红色,如下图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 灰度图蒙版效果

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

到此这篇关于C++ OpenCV实现灰度图蒙版GrayMask的示例代码的文章就介绍到这了,更多相关C++ OpenCV灰度图蒙版内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • python-OpenCV 实现将数组转换成灰度图和彩图

    主要步骤 1.生成普通python数组(bytearray(),os.urandom()) 2.转换成numpy数组(numpy.array()) 3.通过reshape将数组转换到所需的维数 4.以图像的形式显示出来(cv.imshow()) 代码 import os import cv2 as cv import numpy as np # Make an array of 120000 random bytes randomByteArray = bytearray(os.urandom(

  • python opencv将图片转为灰度图的方法示例

    使用opencv将图片转为灰度图主要有两种方法,第一种是将彩色图转为灰度图,第二种是在使用OpenCV读取图片的时候直接读取为灰度图. 将彩色图转为灰度图 import cv2 import numpy as np if __name__ == "__main__": img_path = "timg.jpg" img = cv2.imread(img_path) #获取图片的宽和高 width,height = img.shape[:2][::-1] #将图片缩小

  • python opencv实现灰度图和彩色图的互相转换

    目录 opencv灰度图和彩色图互相转换 注意: 附:python将灰度图转换为RGB彩色图 总结 opencv灰度图和彩色图互相转换 如果摄像头本来就得到3维度红外图那就不用处理直接可以用: import cv2 cap = cv2.VideoCapture(0) ret, image_np = cap.read() 直接转成单通道的灰度图看看能不能用: #如果后面不写0,那就是默认彩色的 # 第一种方式 image = cv2.imread('***/timg4.jpg',0) #第二种方式

  • Python OpenCV 彩色与灰度图像的转换实现

    彩色图像转换为灰度图像 第一种方式通过 imread 读取图像的时候直接设置参数为 0 ,自动转换彩色图像为灰度图像 第二种方式,可以通过 split 进行通道分离,或者叫做读取单个通道,也可以将一个彩色图像分离成 3 个单通道的灰度图像 今天要学习的方法,是通过一个叫做 cvtColor 的方法实现该操作. cv2.cvtColor() 方法用于将图像从一种颜色空间转换为另一种颜色空间. OpenCV 提供了 150 多种 color-space 转换方法.多到用不过来~ 该方法的语法格式为:

  • 基于OpenCV自定义色条实现灰度图上色功能代码

    场景需求        Qt在进行2D图像显示时,有很方便的色条接口,可以让灰度图基于其设计的色条进行上色,比如设置1为红色,0.55为黄色,0.45为绿色,0为蓝色,那么灰度图就会在归一化后按照从蓝到红(从小到大)进行渐变色上色.但是有时候这个接口需要搭配的代码太多,给开发带来一定麻烦,因此我基于其原理写了一个可以替代该功能的函数GrayToColor_ColorBar.        函数原理:首先需要将灰度值图转化为0-255的8通道(uchar)灰度图,运用归一化函数可以实现:之后考虑到

  • C++ OpenCV实现灰度图蒙版GrayMask的示例代码

    目录 需求说明 具体流程 功能函数 C++测试代码 测试效果 需求说明 在对图像进行处理时,经常会有这类需求:想对感兴趣区域进行掩膜处理,只操作掩膜内数据,此时需要搭配掩膜绘制功能,并在绘制过程中希望能区分掩膜区和非掩膜区:除了掩膜本身的线条以外,还希望掩膜内图像是原色,掩膜外图像的颜色进行一定调整:通常可以采用图像透明化或者色彩单通道加深的方式实现. 比如对三通道的图像,可以将掩膜外数据的红通道数值提高,此时该部分图像就会偏红色,如下图1所示. 图1 颜色加深的蒙版效果 但是针对灰度图,因为图

  • Python 使用Opencv实现目标检测与识别的示例代码

    在上章节讲述到图像特征检测与匹配 ,本章节是讲述目标检测与识别.后者是在前者的基础上进一步完善. 在本章中,我们使用HOG算法,HOG和SIFT.SURF同属一种类型的描述符.功能代码如下: import cv2 def is_inside(o, i): ox, oy, ow, oh = o ix, iy, iw, ih = i # 如果符合条件,返回True,否则返回False return ox > ix and oy > iy and ox + ow < ix + iw and o

  • 【JS+CSS3】实现带预览图幻灯片效果的示例代码

    一.前期准备 1.1 案例分析 适用场景:单例布局 1.2 方法论 V视图 HTML+CSS+调试 C js实现控制流程 D数据 优化扩展 二.代码 结构 <div class="slider"><!-- 特效区 --> <div class="main"><!-- 主视图区 --> <div class="main_i"> <div class="caption&quo

  • 使用OpenCV实现人脸图像卡通化的示例代码

    引言 通过前面的文章我们已经了解到OpenCV 是一个用于计算机视觉和机器学习的开源 python 库.它主要针对实时计算机视觉和图像处理.它用于对图像执行不同的操作,这些操作使用不同的技术对图像进行转换.在本文中,我们将实现使用OpenCV将人脸图像卡通化. 让我们从导入必需的库开始! import cv2 import numpy as np 第一次变换(卡通化) 在这个转换中,我们将找到图像的边缘,并使用双边滤波器和位操作符制作一个卡通化的图像. # Reading the Image i

  • 基于PyQt5实现图转文功能(示例代码)

    目录 一.界面PicZ.ui可参考之前的文章如何实现,程序代码如下: 二.main.py实现主要功能程序如下: 三.最后在主程序中加入以上子程序. 四.总结 PyQt是Qt框架的Python语言实现,是最强大的GUI库之一.PyQt提供了一个设计良好的窗口控件集合,具有更方便的操作性.学过VB的同学会知道,相比与VB的使用,在界面设计上元素更丰富. 本文就是基于PyQt5完成的图转文功能,先看界面: 一.界面PicZ.ui可参考之前的文章如何实现,程序代码如下: from PyQt5 impor

  • 基于Python实现千图成像工具的示例代码

    目录 前置 GUI制作 GUI界面设计 逻辑设计 图片处理 修改底图大小 修改组图大小 计算图片填充次数 组图合成 图片合成 GUI打包 千图成像也就是用N张图片组成一张图片的效果.制作方法有很多的,最常见的如用ps.懒人图云.foto-mosaik-edda这些制作. 千图成像的效果我大致分为两类:一为直接用N张图片根据底图的像素颜色.大小,一张张的组成底图,如foto-mosaik-edda:二为用N张图片根据底图的像素大小,组成一张与底图大小相仿的图片,再把二者合成,经调整透明度而成的图片

  • OpenCV实现物体的凸包检测的示例代码

    目录 1. 凸包 2.寻找凸包:convexHull()函数 3.函数解析之theRNG() 4 .circle()函数[回忆] 5.基础示例程序:凸包检测基础 1. 凸包 什么是凸包? 解释:给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸边形,它是包含点集中所有的点. 如下:用人手图来举例说明凸缺陷概念.手周围深色的线描画出凸包,A到H被标出的区域是凸包的各个“缺陷”,这些凸度缺陷提供了手以及手状态的特征表现的方法. 2.寻找凸包:convexHull()函数 说明:convexH

  • Python+OpenCV实现实时眼动追踪的示例代码

    使用Python+OpenCV实现实时眼动追踪,不需要高端硬件简单摄像头即可实现,效果图如下所示. 项目演示参见:https://www.bilibili.com/video/av75181965/ 项目主程序如下: import sys import cv2 import numpy as np import process from PyQt5.QtCore import QTimer from PyQt5.QtWidgets import QApplication, QMainWindow

  • Net core中使用System.Drawing对上传的图片流进行压缩(示例代码)

    目录 直接压缩图片 通过文件流压缩图片 上传到七牛云前压缩图片 部署问题 在Linux中安装 产生原因 解决方案 由于net core 中默认没有System.Drawing,可以通过nuget下载一个来代替System.Drawing.Common 直接压缩图片 /// <summary> /// 图片压缩 /// </summary> /// <param name="sFile">原图片位置</param> /// <para

随机推荐