图像处理-点运算

    图像的点运算就是对图像中的每一个像素点进行计算,为像素点和像素点之间的运算。函数表示形式为 :B(x,y)=f[A(x,y)],其中f为映射函数。点运算有时候被称为灰度变换。

 

1.       线性点运算

线性点运算的函数形式可用线性方程来描述,即:

G(i,j)=T[f(i,j)]=af(i,j)+b

a>1 时,输出图像的对比度增大;a<1时对比度减小。

a=1,把!=0时,图像仅亮度发生变化。

a=-1,b=255时,输出图像的灰度会反转。

以下为C++代码的实现。

Mat LinearPointOperation(Mat& src, double a, double b)
{
    Mat dst(src.rows, src.cols, src.type(),Scalar(0));
    if (src.channels() == 3) {
        for (int i = 0; i < src.rows; i++)
        for (int j = 0; j < src.cols; j++)
      {
          uchar *p = src.ptr<uchar>(i, j);
        uchar *pdst = dst.ptr<uchar>(i, j);
        int ans0 = int(p[0] * a + b);
        int ans1 = int(p[1] * a + b);
        int ans2 = int(p[2] * a + b);
        pdst[0] = ans0 > 255 ? 255 : (ans0 >0 ? ans0 : 0);
        pdst[1] = ans1 > 255 ? 255 : (ans1 >0 ? ans1 : 0);
        pdst[2] = ans2 > 255 ? 255 : (ans2 >0 ? ans2 : 0);
      }
    }
    else if (src.channels() == 1)
    {
        for (int i = 0; i < src.rows; i++) {
        uchar *srcRow = src.ptr(i);
        uchar *dstRow = dst.ptr(i);
        for (int j = 0; j < src.cols; j++)
        {
           int ans0 = int(srcRow[j] * a + b);
           dstRow[j] = ans0 > 255 ? 255 : (ans0 > 0? ans0 : 0);
           }
        }
    }
    return dst;
}

a=2,b=-100时,效果图如下:

1_20190109182236_824.png

a=-1,b=255时:

2_20190109184233_113.png


 

2.       对数变换

s=clog(1+r)

3_20190109184046_674.png 

    其中,c是一个常数,,假设r0,根据上图中的对数函数的曲线可以看出:对数变换,将源图像中范围较窄的低灰度值映射到范围较宽的灰度区间,同时将范围较宽的高灰度值区间映射为较窄的灰度区间,从而扩展了暗像素的值,压缩了高灰度的值,能够对图像中低灰度细节进行增强。;从函数曲线也可以看出,反对数函数的曲线和对数的曲线是对称的,在应用到图像变换其结果是相反的,反对数变换的作用是压缩灰度值较低的区间,扩展高灰度值的区间。

基于OpenCV的实现,其对数变换的代码如下: 

//图像的对数变换 out=c*log(1+src)/log(v) v是对数变换的底数

Mat LogOperation(Mat& src,double c,double v)
{
    float logArr[256];
    for (int i = 0; i < 256; i++) {
        logArr[i] = c * log(i / 255.0 + 1.0) / log(v);
        logArr[i] = logArr[i] > 1 ? 1 : logArr[i];
    }
 
    Mat dst(src.size(), CV_32FC3);
    for (int i = 0; i < src.rows; i++)
        for (int j = 0; j < src.cols; j++)
        {
            uchar *p = src.ptr<uchar>(i, j);
            float *pdst = dst.ptr<float>(i, j);
            pdst[0] = logArr[p[0]];
            pdst[1] = logArr[p[1]];
            pdst[2] = logArr[p[2]];
        }
    return MatFloatToChar(dst);
}

在c=1,v=1.5的情况下:

42_20190109184411_574.png 

 

3.       伽马变换

伽马变换又称指数变换或幂变换,公式:out=c*(src+e)^r

 5_20190109184046_701.png

r>1, 较亮的区域灰度被拉伸,较暗的区域灰度被压缩的更暗,图像整体变暗;

r<1, 较亮的区域灰度被压缩,较暗的区域灰度被拉伸的较亮,图像整体变亮; 

代码实现如下:

//图像的伽马变换 out=c*(src+e)^r  r是伽马变换的指数,e是补偿系数

Mat GamarOperation(Mat& src, double c, double e,double r)
{
    Mat dst(src.size(), CV_32FC3);
    Mat img = MatCharToFloat(src);
    for (int i = 0; i < img.rows; i++)
        for (int j = 0; j < img.cols; j++)
        {
            float *p = img.ptr<float>(i, j);
            float *pdst = dst.ptr<float>(i, j);
            float ans0 = c * pow((p[0]) + e, r);
            float ans1 = c * pow((p[1]) + e, r);
            float ans2 = c * pow((p[2]) + e, r);
            pdst[0] = ans0>1?1:ans0;
            pdst[1] = ans1>1?1:ans1;
            pdst[2] = ans2>1?1:ans2;
        }
    return MatFloatToChar(dst);
}


c=1 e=0 r=0.5时效果图如下:

61_20190109184455_497.png

首页 所有文章 机器人 计算机视觉 自然语言处理 机器学习 编程随笔 关于