计算机图形图像处理 实验二

来源:互联网 发布:英雄联盟 kda 软件 编辑:程序博客网 时间:2024/06/05 08:31

计算机图形图像实验

  • 计算机图形图像实验
    • 一 图像平滑
      • 均值滤波
      • 中值滤波
      • 高斯滤波
      • 实验结果
    • 二 图像锐化
      • Sobel算子
      • Robert算子
      • Prewitt算子
      • Laplacian算子
      • LOG算子
      • 实验结果
    • 三 图像去噪
      • 高斯噪声
      • 椒盐噪声
      • 均匀噪声
      • 实验结果

一. 图像平滑

图像平滑,主要要用到openCV里的函数cvSmooth,如下

/*src 原图像dst 目标图像smoothtype 平滑类型    CV_BLUR 均值滤波    CV_MEDIAN 中值滤波    CV_GAUSSIAN 高斯滤波    CV_BILATERAL 双向滤波size1 平滑操作,窗口的宽,必须是奇数size2 平滑操作,窗口的宽,为0的话和size1大小相等,sigma1 用于高斯滤波sigma2 用于双向滤波*/cvSmooth(cvArr *src,cvArr *dst, int smoothtype, int size1,int size2, double sigma1,double sigma2)

1. 均值滤波

IplImage* blurSmooth(IplImage* src, int size) {    IplImage* dst = cvCreateImage(cvSize(src->width, src->height), src->depth, src->nChannels);    cvSmooth(src, dst, CV_BLUR, size, 0, 0, 0);    return dst;}

2. 中值滤波

/*中值滤波窗口的增加->图像的损坏加大*/IplImage* medianSmooth(IplImage* src, int size) {    IplImage* dst = cvCreateImage(cvSize(src->width, src->height), src->depth, src->nChannels);    cvSmooth(src, dst, CV_MEDIAN, size, 0, 0, 0);    return dst;}

3. 高斯滤波

/*高斯滤波抑制服从正态分布的噪声有效g(x)=exp( -x^2/(2*(sigma^2))*/IplImage* gaussianSmooth(IplImage* src,int size) {    IplImage* dst = cvCreateImage(cvSize(src->width, src->height), src->depth, src->nChannels);    cvSmooth(src, dst, CV_GAUSSIAN, size, 0, 0, 0);    return dst;}

4. 实验结果

这里写图片描述
由以上结果可知,高斯滤波对于含有高斯噪声图像的处理结果较好,仔细看会发现要比均值滤波和中值滤波在细节上会更加清晰一点

椒盐噪声滤波

椒盐噪声图像中,带有随机分布的白点(盐),灰点(椒),中值滤波区中间值,能够有效过滤这两种灰度值的极值,因此,中值滤波对椒盐噪声的处理结果较好

均匀噪声滤波

对于均匀噪声的添加是否正确,这个我不太清楚。按照自己的做法添加均匀噪声后,图像滤波如上所示,就清晰度来说还是高斯滤波的处理效果较好(仔细看可以发现的)

二. 图像锐化

1. Sobel算子

x方向梯度算子Gx

101202101

y方向梯度算子Gy

121000121

012101210210101012

IplImage* sobelSharp(IplImage* src) {     IplImage* dst = cvCreateImage(cvSize(src->width, src->height), src->depth, src->nChannels);    cvSobel(src, dst, 1, 1, 3);    return dst;}

2. Robert算子

梯度采用的是对角方向相邻两像素之差

Δxf(x,y)=f(x,y)f(x1,y1)

[11]

Δyf(x,y)=f(x1,y)f(x,y1)

[11]

IplImage* robertSharp(IplImage* src) {    IplImage* dst = cvCreateImage(cvSize(src->width, src->height), src->depth, src->nChannels);    char *srcData = src->imageData;    int width = dst->width;    int height = dst->height;    int widthStep = dst->widthStep;    char *imageData = dst->imageData;    for (int i = 1; i < height; i++) {        uchar* curLine = (uchar*)(srcData + i * widthStep);        uchar* preLine = curLine - widthStep;        uchar* ptr = (uchar*)(imageData + i * widthStep);        for (int j = 1; j < width; j++) {            for (int rgb = 0; rgb < 3; rgb++) {                double deltaX = curLine[3 * j + rgb] - preLine[3 * (j - 1) + rgb];                double deltaY = curLine[3 * (j - 1) + rgb] - preLine[3 * j + rgb];                double sum = abs(deltaX) + abs(deltaY);                if (sum > 255) sum = 255;                ptr[3 * j + rgb] = sum;            }        }    }    return dst;}

3. Prewitt算子

x方向梯度算子Gx

101101101

y方向梯度算子Gy

111000111

011101110110101011

IplImage* sobelSharp2(IplImage* src) {    IplImage* dst = cvCreateImage(cvSize(src->width, src->height), src->depth, src->nChannels);    char *srcData = src->imageData;    int width = dst->width - 1;    int height = dst->height - 1;    int widthStep = dst->widthStep;    char *imageData = dst->imageData;    for (int i = 1; i < height; i++) {        uchar* curLine = (uchar*)(srcData + i * widthStep);        uchar* preLine = curLine - widthStep;        uchar* nexLine = curLine + widthStep;        uchar* ptr = (uchar*)(imageData + i * widthStep);        for (int j = 1; j < width; j++) {            for (int rgb = 0; rgb < 3; rgb++) {                double deltaX=nexLine[3*(j-1)+rgb] + 2*nexLine[3*j+rgb] + nexLine[3*(j+1)+ rgb]                    - preLine[3*(j-1)+rgb] -2*preLine[3*j+rgb] - preLine[3*(j+1)+rgb];                double deltaY=preLine[3*(j+1)+rgb]+2*curLine[3*(j+1)+rgb]+nexLine[3*(j+ 1)+rgb]                    - preLine[3*(j-1)+rgb] - 2*curLine[3*(j-1)+rgb]-nexLine[3 * (j - 1) + rgb];                double sum = (abs(deltaX)+ abs(deltaY))/4;                if (sum > 255) sum = 255;                ptr[3 * j + rgb] = sum;            }        }    }    return dst;}

4. Laplacian算子

010141010111181111

IplImage* laplaceSharp(IplImage* src) {    IplImage* dst = cvCreateImage(cvSize(src->width, src->height), src->depth, src->nChannels);    cvLaplace(src, dst, 3);    return dst;}

5. LOG算子

/*LOG算子先使用gaussian算子 光滑滤波处理在使用Laplace算子 进行锐化*/IplImage* logSharp(IplImage* src) {    IplImage* dst = cvCreateImage(cvSize(src->width, src->height), src->depth, src->nChannels);    cvSmooth(src, dst, CV_GAUSSIAN, 3, 0, 0, 0);    cvLaplace(dst, dst, 3);    return dst;}

6. 实验结果

  1. 对正常图像进行锐化

    sharp1_1

    sharp1_2

  2. 对高斯噪声图像进行锐化

    sharp2_1

    sharp2_2

  3. 对含有椒盐噪声的图像进行锐化

    sharp3_1

    sharp3_2

  4. 对均匀噪声的图像进行锐化

    sharp4_1

    sharp4_2

算子比较

Robert算子,边缘定位精度较高,但容易丢失一部分边缘,同时由于图像没经过平滑处理,因此不具备抑制噪声的能力。该算子对具有陡峭边缘且含噪声少的图像效果较好。

Sobel算子和Prewitt算子:都是对图像先做加权平滑处理,然后再做微分运算,所不同的是平滑部分的权值有些差异,因此对噪声具有一定的抑制能力,但不能完全排除检测结果中出现的虚假边缘。检测的边缘容易出现多像素宽度

Laplacian算子:对噪声非常敏感,它使噪声成分得到加强,这两个特性使得该算子容易丢失一部分边缘的方向信息,造成一些不连续的检测边缘,同时抗噪声能力比较差。

LOG算子:该算子首先用高斯函数对图像作平滑滤波处理,然后才使用Laplacian算子检测边缘,因此克服了Laplacian算子抗噪声能力比较差的缺点,但是在抑制噪声的同时也可能将原有的比较尖锐的边缘也平滑掉了,造成这些尖锐边缘无法被检测到。

三. 图像去噪

1. 高斯噪声

p(z)=12πσe(zμ)22σ2

ZN[μ,σ2]

这里使用了Box-Muller转化:

假设U1, U2是(0, 1)之间均匀分布的两个独立的随机变量,

Z0=Rcos(θ)=2lnU1cos(2πU2)

Z1=Rcos(θ)=2lnU1sin(2πU2)

Z0,Z1是两个标准正态分布的随机变量即 ZN[0,1]

将标准正态分布转化为非标准正态分布 FN[μ,σ2]

f=zσ+μ

如下转化代码摘自 https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform

(有适当改动)

double generateGaussianNoise(double mu, double sigma){    const double epsilon = std::numeric_limits<double>::min();    const double two_pi = 2.0*3.14159265358979323846;    static double z0, z1;    static bool generate = true;    generate = !generate;    if (generate)        return z1 * sigma + mu;    double u1, u2;    do    {        u1 = rand() * (1.0 / RAND_MAX);        u2 = rand() * (1.0 / RAND_MAX);    } while (u1 <= epsilon);    double sqrt_u = sqrt(-2.0 * log(u1));    u2 *= two_pi;    //    z0 = sqrt_u * cos(u2);    z1 = sqrt_u * sin(u2);    return z0 * sigma + mu;}

2. 椒盐噪声

salt 盐 白色,指图像中的白点,pepper胡椒 黑色 ,图像中黑色的点

/*src 原图像n 在图像中随机生成n个白点和黑点*/IplImage* saltAndPepperNoise(IplImage* src, int n) {    IplImage* dst = src;    int width = dst->width;    int height = dst->height;    int widthStep = dst->widthStep;    char *imageData = dst->imageData;    //添加盐噪声    for (int i = 0; i < n; i ++) {        int x = rand() % width;        int y = rand() % height;        uchar* ptr = (uchar*)(imageData + y * widthStep);        ptr[3 * x] = 255;        ptr[3 * x + 1] = 255;        ptr[3 * x + 2] = 255;    }    //添加胡椒噪声    for (int i = 0; i < n; i++) {        int x = rand() % width;        int y = rand() % height;        uchar* ptr = (uchar*)(imageData + y * widthStep);        ptr[3 * x] = 0;        ptr[3 * x + 1] = 0;        ptr[3 * x + 2] = 0;    }    return dst;}

3. 均匀噪声

(0,1)的均匀分布,ZU[12,112],σ2=112

转化为FU[μ,σ2], 任意的均值为μ, 方差为σ2的均匀分布。

f=(z12)12σ+μ

,这样可以得到我们自己想要的均匀分布

/*均匀噪声*/IplImage* uniformNoise(IplImage* src, double mu, double sigma) {    IplImage* dst = src;    int width = dst->width * dst->nChannels;    int height = dst->height;    int widthStep = dst->widthStep;    char *imageData = dst->imageData;    for (int i = 0; i < height; i++) {        uchar* ptr = (uchar*)(imageData + i * widthStep);        for (int j = 0; j < width; j++) {            double p1 = ptr[j] + mu + cvSqrt(12) * sigma * (rand()/(double) RAND_MAX - 0.5);            if (p1 < 0) p1 = 0;            if (p1 > 255) p1 = 255;            ptr[j] = p1;        }    }    return dst;}

4. 实验结果

三种噪声的添加

由实验结果可以得知,高斯噪声、均匀噪声,影响的是图片的没一个像素,而椒盐噪声影响的是图片的若干个点。

对于这几个图像的滤波,就不再演示了,在前面已经涉及到了。

0 0