基于opencv的c++图像处理(灰度变换)

前言

基于opencv的c++接口,实现常用的图像灰度变换方法,包括了线性变换、图像反转、对数变换和伽马变换。

相关的opencv接口解析

CV_EXPORTS_W void normalize( InputArray src, InputOutputArray dst, double alpha = 1, double beta = 0,
                             int norm_type = NORM_L2, int dtype = -1, InputArray mask = noArray());

函数 cv::normalize 标准化缩放和移动输入数组元素
当 normType=NORM_MINMAX 时(仅适用于密集数组)。可选掩码指定要规范化的子数组。这意味着在子数组上计算范数或 min-n-max,然后修改该子数组以进行归一化。如果您只想使用掩码计算范数或最小值-最大值但修改整个数组,则可以使用 norm 和 Mat::convertTo。
@param src 输入数组。
@param dst 与 src 大小相同的输出数组。
@param alpha norm value 规范化到或范围归一化情况下的范围下限。
@param beta 范围归一化情况下的范围上限;它不用于规范标准化。
@param norm_type 规范化类型(参见 cv::NormTypes)。
@param dtype 为负时,输出数组与 src 类型相同;否则,它具有与 src 相同数量的通道和深度 =CV_MAT_DEPTH(dtype)。
@param mask 可选操作掩码。

enum NormTypes {

                NORM_INF       = 1,

                 NORM_L1        = 2,

                 NORM_L2        = 4,

                 NORM_L2SQR     = 5,

                 NORM_HAMMING   = 6,

                 NORM_HAMMING2  = 7,
                 NORM_TYPE_MASK = 7,
                 NORM_RELATIVE  = 8,
                 NORM_MINMAX    = 32
               };
CV_EXPORTS_W void convertScaleAbs(InputArray src, OutputArray dst,
                                  double alpha = 1, double beta = 0);

函数可用于缩放,计算绝对值,并将结果转换为 8 位。
在输入数组的每个元素上,函数 convertScaleAbs 依次执行三个操作:缩放、取绝对值、转换为无符号 8 位类型。
在多通道数组的情况下,该函数独立处理每个通道。当输出不是 8 位时,可以通过调用 Mat::convertTo 方法(或使用矩阵表达式)模拟该操作,然后计算结果的绝对值。
@param src 输入数组。
@param dst 输出数组。
@param alpha 可选比例因子。
@param beta 可选增量添加到缩放值。

常用灰度变换公式

图像反转公式:s=255-r,其中,r表示原始图像的灰度级,s表示变换后的灰度级。
对数变换公式:s=c _log(1+r),其中,r表示原始图像的灰度级,s表示变换后的灰度级,c为常数。
伽马变换公式 :s=c_r^y,其中,r表示原始图像的灰度级,s表示变换后的灰度级,c为比例系数,y为幂数。
线性变换公式:s=a*r+b,其中,r表示原始图像的灰度级,s表示变换后的灰度级,a为比例系数,b为平移系数。

示例代码

grayTransform.h

#pragma once

#include
#include
#include
#include

using namespace std;
using namespace cv;
#define PROCESS_IMG_SUCESS 0
#define PROCESS_IMG_FAIL 1

namespace ImgEnhance
{

    class GrayscaleTransform
    {

    public:
        GrayscaleTransform() { cout << "GrayscaleTransform is being created" << endl; }
        ~GrayscaleTransform() { cout << "GrayscaleTransform is being deleted" << endl; }

        int ImageInverse(cv::Mat srcImage, cv::Mat &dstImage);
        int ImageLogTransform(cv::Mat srcImage, cv::Mat &dstImage,float c);
        int ImageGammaTransform(cv::Mat srcImage, cv::Mat &dstImage, float c,float y);
        int ImageLinearTransform(cv::Mat srcImage, cv::Mat &dstImage, float a, float b);

    };

}

grayTransform.cpp

#include"grayTransform.h"

int ImgEnhance::GrayscaleTransform::ImageInverse(cv::Mat srcImage, cv::Mat &dstImage)
{
    if (!srcImage.data || srcImage.channels() != 1)
    {
        return 1;
    }
    int height = srcImage.rows;
    int width = srcImage.cols;

    Mat dst = Mat(height, width,CV_8UC1);
    for (int i = 0; i < height; i++)
    {
        uchar* p1 = dst.ptr<uchar>(i);
        uchar* p2 = srcImage.ptr<uchar>(i);
        for (int j = 0; j < srcImage.cols; j++)
        {
            p1[j] = 255 - p2[j];
        }
    }

    dstImage = dst.clone();

    return 0;
}

int ImgEnhance::GrayscaleTransform::ImageLogTransform(cv::Mat srcImage, cv::Mat &dstImage, float c)
{
    if (!srcImage.data || srcImage.channels() != 1)
    {
        return 1;
    }
    int height = srcImage.rows;
    int width = srcImage.cols;

    float pixels[256];
    for (int i = 0; i < 256; i++)
    {
        pixels[i] = c*log(1 + i);
    }

    Mat imageLog(height, width, CV_32FC1);
    for (int i = 0; i<height; i++)
    {
        float* p1 = imageLog.ptr<float>(i);
        uchar* p2 = srcImage.ptr<uchar>(i);
        for (int j = 0; j<width; j++)
        {
            p1[j] = pixels[p2[j]];
        }
    }

    normalize(imageLog, imageLog, 0, 255, NORM_MINMAX);

    convertScaleAbs(imageLog, imageLog);

    dstImage = imageLog.clone();

    return 0;

}

int ImgEnhance::GrayscaleTransform::ImageGammaTransform(cv::Mat srcImage, cv::Mat &dstImage, float c, float y)
{
    if (!srcImage.data || srcImage.channels() != 1)
    {
        return 1;
    }
    int height = srcImage.rows;
    int width = srcImage.cols;

    float pixels[256];
    for (int i = 0; i < 256; i++)
    {
        pixels[i] = c*powf(i, y);
    }

    Mat imageGamma(height, width, CV_32FC1);
    for (int i = 0; i<height; i++)
    {
        float* p1 = imageGamma.ptr<float>(i);
        uchar* p2 = srcImage.ptr<uchar>(i);
        for (int j = 0; j<width; j++)
        {
            p1[j] = pixels[p2[j]];
        }
    }

    normalize(imageGamma, imageGamma, 0, 255, NORM_MINMAX);

    convertScaleAbs(imageGamma, imageGamma);

    dstImage = imageGamma.clone();

    return 0;

}

int ImgEnhance::GrayscaleTransform::ImageLinearTransform(cv::Mat srcImage, cv::Mat &dstImage, float a, float b)
{

    if (!srcImage.data || srcImage.channels() != 1)
    {
        return 1;
    }
    int height = srcImage.rows;
    int width = srcImage.cols;

    float pixels[256];
    for (int i = 0; i < 256; i++)
    {
        pixels[i] = a*i+b;
    }

    Mat imageLinear(height, width, CV_32FC1);
    for (int i = 0; i<height; i++)
    {
        float* p1 = imageLinear.ptr<float>(i);
        uchar* p2 = srcImage.ptr<uchar>(i);
        for (int j = 0; j<width; j++)
        {
            p1[j] = pixels[p2[j]];
        }
    }

    normalize(imageLinear, imageLinear, 0, 255, NORM_MINMAX);

    convertScaleAbs(imageLinear, imageLinear);

    dstImage = imageLinear.clone();

    return 0;
}

test.cpp

#include"grayTransform.h"

ImgEnhance::GrayscaleTransform ImgG;

int main()
{

    cv::Mat srcImage = cv::imread("flower.jpg");
    if (!srcImage.data)
    {
        return 1;
    }
    cv::namedWindow("原始图", 0);
    cv::imshow("原始图", srcImage);

    cv::Mat srcGray;
    if (srcImage.channels() == 3)
    {
        cv::cvtColor(srcImage, srcGray, COLOR_RGB2GRAY);
    }
    else
    {
        srcGray = srcImage.clone();
    }
    cv::namedWindow("灰度图", 0);
    cv::imshow("灰度图", srcGray);

    cv::Mat inverseMat;

    ImgG.ImageInverse(srcGray, inverseMat);
    cv::namedWindow("灰度反转图", 0);
    cv::imshow("灰度反转图", inverseMat);

    cv::Mat imageLogTransformMat;
    float cl = 10;

    ImgG.ImageLogTransform(srcGray, imageLogTransformMat,cl);
    cv::namedWindow("对数变换图", 0);
    cv::imshow("对数变换图", imageLogTransformMat);

    cv::Mat imageGammaTransformMat;
    float cg = 1;
    float yg = 0.5;

    ImgG.ImageGammaTransform(srcGray, imageGammaTransformMat, cg,yg);
    cv::namedWindow("伽马变换图", 0);
    cv::imshow("伽马变换图", imageGammaTransformMat);

    cv::Mat imageLinearTransformMat;
    float a = 0.5;
    float b = 1;

    ImgG.ImageGammaTransform(srcGray, imageLinearTransformMat, a, b);
    cv::namedWindow("线性变换图", 0);
    cv::imshow("线性变换图", imageLinearTransformMat);

    cv::waitKey(0);

    return 0;

}

结果图

基于opencv的c++图像处理(灰度变换)

Original: https://blog.csdn.net/qq_40118285/article/details/126935458
Author: daydayup_cy
Title: 基于opencv的c++图像处理(灰度变换)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/641362/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球