参考资料:
c++ 深浅拷贝
1、灰度图片结构体封装
- 想进一步封装相关元素,利用结构体的形式来进行参数。原始结构体如下所示。
typedef struct GrayFrameInfo {
int width = 0; // 宽度
int height = 0; // 高度
uint8_t** arr = nullptr; // 数据指针
}GrayFrame;
- 在进行引用的时候,下面的灰度线性变换中,对结果图片直接进行形参赋值的时候,我们会发现,结果图片和参数图片的指针实际指向同一地址空间。此时,就是 C++ 中相关浅拷贝、深拷贝问题。
struct GrayFrameInfo grayLinearTrans(struct GrayFrameInfo img, double k, double b)
{
GrayFrame dstImg = img;
for (int i = 0; i < img.height; i++) {
for (int j = 0; j < img.width; j++) {
uint8_t gray = (uint8_t)(img.arr[i][j] * k + b);
dstImg.arr[i][j] = Clipping(gray, 0, 255);
}
}
return dstImg;
}
- 解决方案:利用重载操作符,来实现地址空间的重新分配。
typedef struct GrayFrameInfo {
int width = 0; // 宽度
int height = 0; // 高度
uint8_t** arr = nullptr; // 数据指针
// 重加载 = 操作符,重新开辟一份新的地址空间来进行数据指针的指向,但此时并没有进行图像像素值的拷贝,只是开辟了地址空间
GrayFrameInfo &operator = (GrayFrameInfo &temp)
{
this->width = temp.width;
this->height = temp.height;
// 重新开辟地址空间,但此时空间内的数据值,并没有进行拷贝
this->arr = new uint8_t * [temp.height]();
for (int i = 0; i < temp.height; i++) {
this->arr[i] = new uint8_t[temp.width]();
}
return *this;
};
}GrayFrame;
- 相关说明:在使用重载操作符之后,发现在函数的引用时,会出现重载操作符的引用错误,就更改为函数的形式。
struct GrayFrameInfo {
int width = 0; // 宽度
int height = 0; // 高度
uint8_t** arr = nullptr; // 数据指针
GrayFrameInfo createNewImgSpace(GrayFrameInfo& temp)
{
this->width = temp.width;
this->height = temp.height;
this->arr = new uint8_t * [temp.height]();
for (int i = 0; i < temp.height; i++) {
this->arr[i] = new uint8_t[temp.width]();
}
return *this;
}
GrayFrameInfo createNewImgSpace(int dstWidth, int dstHeight)
{
this->width = dstWidth;
this->height = dstHeight;
this->arr = new uint8_t * [dstHeight]();
for (int i = 0; i < dstHeight; i++) {
this->arr[i] = new uint8_t[dstWidth]();
}
return *this;
}
};
- 调用
GrayFrameInfo dstImg = dstImg.createNewImgSpace(img);
2、线性变化
- 介绍
- 实现
/************************************************************
*Function: grayLinearTrans
*Description: 灰度图像的线性变换
*Params: img - GrayFrame 类型结构体
* k - 线性变换的斜率
* b - 线性变换的截距
*Return: dstImg - 线性变换之后的结果
************************************************************/
struct GrayFrameInfo grayLinearTrans(struct GrayFrameInfo img, double k, double b)
{
// 利用重载操作符来完成数据空间的开辟,若是 GrayFrame dstImg = img; 只实现了一层浅拷贝,图像数据空间共用
GrayFrameInfo dstImg = dstImg.createNewImgSpace(img);
for (int i = 0; i < img.height; i++) {
for (int j = 0; j < img.width; j++) {
uint8_t gray = (uint8_t)(img.arr[i][j] * k + b);
dstImg.arr[i][j] = Clipping(gray, 0, 255);
}
}
return dstImg;
}
3、对数变化
-
介绍
-
实现
/************************************************************
*Function: grayLogTrans
*Description: 灰度图像的对数变换
*Params: img - GrayFrame 类型结构体
* c - 对数变换的增益
*Return: dstImg - 线性变换之后的结果
************************************************************/
struct GrayFrameInfo grayLogTrans(struct GrayFrameInfo img, double c)
{
GrayFrameInfo dstImg = dstImg.createNewImgSpace(img);
for (int i = 0; i < img.height; i++) {
for (int j = 0; j < img.width; j++) {
uint8_t gray = (uint8_t)(c * log((double)img.arr[i][j] + 1));
dstImg.arr[i][j] = Clipping(gray, 0, 255);
}
}
return dstImg;
}
4、伽马变化
- 介绍
- 实现
/************************************************************
*Function: grayGammaTrans
*Description: 灰度图像的伽马变换
*Params: img - GrayFrame 类型结构体
* e - 伽马变换的补偿系数
* r - 伽马系数
*Return: dstImg - 线性变换之后的结果
************************************************************/
struct GrayFrameInfo grayGammaTrans(struct GrayFrameInfo img, double e, double r)
{
GrayFrameInfo dstImg = dstImg.createNewImgSpace(img);
for (int i = 0; i < img.height; i++) {
for (int j = 0; j < img.width; j++) {
uint8_t gray = (uint8_t)(pow((e + img.arr[i][j]) / 255.0, r) * 255);
dstImg.arr[i][j] = Clipping(gray, 0, 255);
}
}
return dstImg;
}