前言
基于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;
}
结果图
Original: https://blog.csdn.net/qq_40118285/article/details/126935458
Author: daydayup_cy
Title: 基于opencv的c++图像处理(灰度变换)
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/641362/
转载文章受原作者版权保护。转载请注明原作者出处!