小记录:关于opencv3.X中的gauss滤波和图像类型转换

本文探讨了在Windows环境下使用OpenCV 3.2和QT 4.8.6时遇到的cvSmooth函数错误,并提供了可能的解决方案及替代方法。同时记录了QImage、Mat和IplImage之间的转换技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

**我的开发环境:**windows下opencv3.2,QT4.8.6。
遇到的问题是:smooth = cvCreateImage(cvGetSize(iplImg),IPL_DEPTH_8U,1);
cvSmooth(iplImg,smooth,CV_GAUSSIAN,3,0,0);

**所报错误为:**OpenCV Error: Assertion failed (dst.size() == src.size() && (smooth_type == CV_BLUR_NO_SCALE || dst.type() == src.type()))。程序执行后卡死退出,但是同样的代码在Linux中却可以执行。
应该不是申请内存那块。同样的方式做“灰度化”就没有问题。初步怀疑是编译器问题。同时也请看到这篇文章的大牛们回复具体讨论。
为了达到Gauss滤波的目的先用GaussianBlur函数代替cvSmooth平滑滤波,没有问题。
———-
opencv中的转换挺重要,2.X和3.X有的会有些差别,而且方法不局限一种。因为我的环境是QT,在这里对QImage Mat IplImage转换记录下:
QImage—>IplImage:

QImage* img;
IplImage *iplImg;
int nChannel = 0;
    nChannel = img->format();
    qDebug()<<"img format is:"<<img->format();
    if( nChannel==0 )
    {
        return;
    }
    else
    {
        iplImg=cvCreateImageHeader(cvSize(img->width(),img->height()),8,nChannel);
        iplImg->imageData=(char*)img->bits();
        if(nChannel==3)
        {
            cvConvertImage(iplImg,iplImg,CV_CVTIMG_SWAP_RB);
        }

IplImage—>QImage: 摘自

QImage* CjwIplToQImg(const IplImage *cvImg)
{
if(!cvImg)
return NULL;
IplImage* temp=NULL;
temp=cvCloneImage(cvImg);
cvCvtColor(cvImg,temp,CV_BGR2RGB);
uchar* imgData = (uchar*)(temp->imageData);
QImage *qImg=new QImage(imgData,temp->width,temp->height,QImage::Format_RGB888);
return qImg;
cvReleaseImage(&temp);
delete imgData;
}

IplImage—>Mat:

  IplImage iplImg;
  Mat matimg;
    matimg = cvarrToMat(iplImg);

Mat—>IplImage:

iplImg= IplImage(matimg);

Mat—>QImage:摘自

QImage cvMat2QImage(const cv::Mat& mat)
{
    // 8-bits unsigned, NO. OF CHANNELS = 1
    if(mat.type() == CV_8UC1)
    {
        QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
        // Set the color table (used to translate colour indexes to qRgb values)
        image.setNumColors(256);
        for(int i = 0; i < 256; i++)
        {
            image.setColor(i, qRgb(i, i, i));
        }
        // Copy input Mat
        uchar *pSrc = mat.data;
        for(int row = 0; row < mat.rows; row ++)
        {
            uchar *pDest = image.scanLine(row);
            memcpy(pDest, pSrc, mat.cols);
            pSrc += mat.step;
        }
        return image;
    }
    // 8-bits unsigned, NO. OF CHANNELS = 3
    else if(mat.type() == CV_8UC3)
    {
        // Copy input Mat
        const uchar *pSrc = (const uchar*)mat.data;
        // Create QImage with same dimensions as input Mat
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
        return image.rgbSwapped();
    }
    else if(mat.type() == CV_8UC4)
    {
        // Copy input Mat
        const uchar *pSrc = (const uchar*)mat.data;
        // Create QImage with same dimensions as input Mat
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
        return image.copy();
    }
    else
    {
        return QImage();
    }
}

QImage—>Mat:摘自

Mat QImage2cvMat(QImage image)
{
    cv::Mat mat;
    switch(image.format())
    {
    case QImage::Format_ARGB32:
    case QImage::Format_RGB32:
    case QImage::Format_ARGB32_Premultiplied:
        mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.bits(), image.bytesPerLine());
        break;
    case QImage::Format_RGB888:
        mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.bits(), image.bytesPerLine());
        cv::cvtColor(mat, mat, CV_BGR2RGB);
        break;
    case QImage::Format_Indexed8:
        mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.bits(), image.bytesPerLine());
        break;
    }
    return mat;
}
<think>好的,我需要帮助用户使用OpenCV图像添加高斯噪声并应用不同尺寸的均值滤波。首先,用户提到了高斯噪声均值滤波,所以我得回忆一下相关的OpenCV函数。 添加高斯噪声的话,应该先生成一个原图同样大小的噪声矩阵,然后用cv2.add()叠加到原图上。这里需要注意,高斯噪声的参数,比如均值标准差,用户没有指定,可能需要默认值,比如均值0,标准差25。然后,噪声应该是高斯分布,所以要用numpy生成正态分布的随机数,再转换为uint8类型,避免数据溢出。 接下来是均值滤波OpenCV中的均值滤波函数是cv2.blur(),需要指定核的大小,比如3x37x7。用户需要分别应用这两种核,得到两个处理后的图像。 然后,展示图像部分,需要将原图、加噪后的图、3x3滤波结果7x7滤波结果放在同一个窗口中。可能需要使用matplotlib的子图功能,或者用OpenCV的hconcatvconcat来拼接图像。不过考虑到用户可能希望在一个图里显示,用matplotlib更合适,可以分成四个子图,分别显示四个图像,并添加标题。 需要注意的还有图像的读取显示时的颜色通道问题。如果原图是彩色图,添加噪声时需要每个通道都加,而滤波也会分别处理每个通道。但cv2.blur默认会处理彩色图像,所以不需要额外操作。 另外,用户提供的引用中提到cv2.add()的使用,这里添加噪声应该用numpy的加法还是OpenCV的?因为numpy的加法会模运算,而OpenCV的加法会饱处理,所以为了避免超出255的值变成模,应该用OpenCV的加法,即cv2.add()。不过之前的引用中用户提到可以用numpy或cv2.add,但正确的做法是使用cv2.add,或者确保numpy的加法正确。不过生成高斯噪声后,可能需要先将原图转换为浮点数,加上噪声,再裁剪到0-255范围,再转回uint8,这样更稳妥。 或者,生成高斯噪声后,使用cv2.addWeighted(),但可能直接相加更简单。需要确认步骤是否正确。 然后,代码的步骤大致是: 1. 读取图像,假设是train1.jpg。 2. 生成高斯噪声,使用np.random.normal,参数为均值0,标准差25,大小图像相同。 3. 将噪声添加到原图,注意类型转换,避免溢出。 4. 应用3x37x7的均值滤波。 5. 显示所有图像在一个窗口中。 可能还需要处理图像路径的问题,比如检查文件是否存在。但用户可能已经确保图像存在,所以代码中可能需要异常处理,但用户可能不需要那么复杂。 现在,关于引用的问题,用户提供的引用中有引用[2]提到cv.add(),所以添加噪声时用cv2.add()更合适?或者是否需要?比如,原图噪声都是uint8类型,直接相加可能导致溢出,所以正确的做法是先转换为更大的数据类型,相加后再裁剪到0-255。或者,先生成高斯噪声,然后将噪声转换为与原图相同的数据类型,再使用cv2.add。或者,生成高斯噪声矩阵,然后与原图相加,并确保值在0-255之间。 比如,原图是uint8,添加高斯噪声的步骤可能如下: - 生成高斯噪声矩阵,使用np.random.normal(0, sigma, image.shape).astype(np.int16) - 将原图转换为int16类型,然后相加,再裁剪到0-255,再转回uint8。 或者,先生成浮点数噪声,然后转换为int,再相加。这样可以避免溢出。比如: noise = np.random.normal(0, 25, img.shape).astype(np.int16) noisy_img = cv2.add(img.astype(np.int16), noise) noisy_img = np.clip(noisy_img, 0, 255).astype(np.uint8) 但可能更简单的方式是生成适当范围的噪声,直接使用cv2.add,或者使用numpy的运算,但需要注意数据类型。 根据引用[2],可以用numpy的加法,但需要处理溢出。或者使用cv2.add,但cv2.add的参数需要是相同类型,所以可能需要将噪声转换为与原图相同的类型,比如uint8,但这样可能损失精度。或者,先生成高斯噪声为浮点,然后缩放到0-255,再转换为uint8。不过这样可能不符合高斯分布的特性。 可能更好的方法是: 原图转换为浮点类型,添加高斯噪声(浮点数),然后裁剪到0-255,再转回uint8。例如: img_float = img.astype(np.float32) noise = np.random.normal(0, 25, img.shape).astype(np.float32) noisy_img_float = img_float + noise noisy_img = np.clip(noisy_img_float, 0, 255).astype(np.uint8) 这样处理更准确,因为高斯噪声可能有正负值,叠加到浮点图像后再裁剪,可以保留更多信息。 然后,应用均值滤波,使用cv2.blur,参数分别是(3,3)(7,7)。 显示部分,用matplotlib创建四个子图,分别显示原图、加噪图、3x3滤波、7x7滤波。可能需要调整图像的颜色通道,因为OpenCV读取的是BGR,而matplotlib显示的是RGB。所以需要将图像从BGR转换为RGB,或者在显示时转换。 所以,完整的步骤是: 1. 读取图像,使用cv2.imread,注意路径正确。 2. 生成高斯噪声并添加到图像3. 应用两种均值滤波。 4. 转换图像颜色空间为RGB,以便正确显示。 5. 使用matplotlib显示四个图像。 代码示例: import cv2 import numpy as np import matplotlib.pyplot as plt # 读取图像 img = cv2.imread(&#39;train1.jpg&#39;) # 添加高斯噪声 mean = 0 sigma = 25 noise = np.random.normal(mean, sigma, img.shape).astype(np.float32) img_float = img.astype(np.float32) noisy_img_float = img_float + noise noisy_img = np.clip(noisy_img_float, 0, 255).astype(np.uint8) # 应用均值滤波 blur3x3 = cv2.blur(noisy_img, (3,3)) blur7x7 = cv2.blur(noisy_img, (7,7)) # 转换为RGB用于显示 img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) noisy_rgb = cv2.cvtColor(noisy_img, cv2.COLOR_BGR2RGB) blur3x3_rgb = cv2.cvtColor(blur3x3, cv2.COLOR_BGR2RGB) blur7x7_rgb = cv2.cvtColor(blur7x7, cv2.COLOR_BGR2RGB) # 创建子图 plt.figure(figsize=(12,8)) plt.subplot(2,2,1) plt.imshow(img_rgb) plt.title(&#39;Original Image&#39;) plt.axis(&#39;off&#39;) plt.subplot(2,2,2) plt.imshow(noisy_rgb) plt.title(&#39;Image with Gaussian Noise&#39;) plt.axis(&#39;off&#39;) plt.subplot(2,2,3) plt.imshow(blur3x3_rgb) plt.title(&#39;3x3 Mean Filter&#39;) plt.axis(&#39;off&#39;) plt.subplot(2,2,4) plt.imshow(blur7x7_rgb) plt.title(&#39;7x7 Mean Filter&#39;) plt.axis(&#39;off&#39;) plt.tight_layout() plt.savefig(&#39;result.png&#39;) plt.show() 这样应该能完成任务。需要注意参数如sigma的值,用户可能需要调整,但示例中设为25。此外,保存结果图像使用plt.savefig。 现在,根据引用[2],添加两个图像应该用cv.add或numpy操作,但这里高斯噪声是生成的矩阵,所以用numpy的加法更直接,但要注意数据类型。在代码中,使用浮点数运算并裁剪,确保正确。 此外,引用[3]提到卷积时扩展边界的问题,但均值滤波OpenCV中默认处理边界的方式应该是使用BORDER_DEFAULT,可能包括镜像或其他方式,但用户不需要特别处理,因为cv2.blur会自动处理边界。 最后,生成相关问题,需要围绕高斯噪声均值滤波的应用、参数影响、不同滤波核效果比较等。</think>以下是使用OpenCV实现图像高斯噪声添加均值滤波的完整解决方案: ### 1. 实现步骤 1. **读取图像**:使用`cv2.imread()`加载原始图像 2. **添加高斯噪声**:通过numpy生成正态分布随机数矩阵叠加到原图 3. **均值滤波处理**:分别应用3x37x7滤波核 4. **结果可视化**:使用matplotlib展示四图对比 ```python import cv2 import numpy as np import matplotlib.pyplot as plt # 读取图像 img = cv2.imread(&#39;train1.jpg&#39;) # 添加高斯噪声 def add_gaussian_noise(image, mean=0, sigma=25): row, col, ch = image.shape gauss = np.random.normal(mean, sigma, (row, col, ch)) noisy = image.astype(np.float32) + gauss return np.clip(noisy, 0, 255).astype(np.uint8) noisy_img = add_gaussian_noise(img) # 执行均值滤波 blur_3x3 = cv2.blur(noisy_img, (3,3)) # 引用[3]边界处理说明 blur_7x7 = cv2.blur(noisy_img, (7,7)) # 创建对比图 plt.figure(figsize=(15,10)) images = [ cv2.cvtColor(img, cv2.COLOR_BGR2RGB), cv2.cvtColor(noisy_img, cv2.COLOR_BGR2RGB), cv2.cvtColor(blur_3x3, cv2.COLOR_BGR2RGB), cv2.cvtColor(blur_7x7, cv2.COLOR_BGR2RGB) ] titles = [&#39;原图像&#39;, &#39;高斯噪声图像&#39;, &#39;3x3均值滤波&#39;, &#39;7x7均值滤波&#39;] for i in range(4): plt.subplot(2,2,i+1) plt.imshow(images[i]) plt.title(titles[i]) plt.axis(&#39;off&#39;) plt.tight_layout() plt.savefig(&#39;noise_filter_comparison.jpg&#39;) plt.show() ``` ### 2. 关键参数说明 - **高斯噪声参数**:`mean=0`控制噪声中心位置,`sigma=25`决定噪声强度 - **滤波核尺寸**:3x3核保留更多细节,7x7核平滑效果更明显[^3] - **边界处理**:OpenCV自动进行边界扩展(默认使用BORDER_REFLECT_101) ### 3. 效果对比 | 滤波核尺寸 | 细节保留 | 噪声抑制 | 计算效率 | |-----------|----------|----------|----------| | 3x3 | ★★★★ | ★★ | ★★★★ | | 7x7 | ★★ | ★★★★ | ★★ | $$ \text{均值滤波公式:} \quad dst(x,y) = \frac{1}{ksize.width \times ksize.height} \sum_{i,j} kernel(i,j) \cdot src(x+i,y+j) $$ [^1]: 椒盐噪声处理示例 [^2]: OpenCV图像叠加操作规范 : 卷积边界处理机制 [^4]: 卷积核设计原理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值