开始之前

在上一篇我们实现了读取噪声图像, 然后 进行三种形式的均值滤波得到结果, 由于我们自己写的均值滤波未作边缘处理, 所以效果有一定的下降, 但是总体来说, 我们得到的结果能够说明我们的算法执行之后得到的图像噪声更低, 图像更清晰. 但是也会造成图像的模糊, 导致部分细节丢失. 在这一章中,我们介绍一下中值滤波及其实现

摘要

首先介绍了中值滤波的原理, 给出其实现思路,并根据思路实现了 C++ 的代码, 然后 同样测试 opencv 自带的中值滤波, 同样的测试图像, 得到对比结果, 分析代码的实现过程, .

正文

中值滤波原理

中值滤波(Media Filter)就是对于图像的每一个点计算其邻域窗口的像素序列中值, 可以表示为:
g(x,y)=meida(i,j)∈Sf(i,j)g(x,y) = meida_{(i,j) \in S}f(i,j) g(x,y)=meida(i,j)∈S​f(i,j)
核心就是将相应窗口内的像素值进行排列, 我们之前也说过, 我们选择的窗口为奇数尺寸, 所以我们能够保证窗口内的像素个数也是奇数个, 这样我们可以保证取得唯一的中值, 相应的设置为该点的目标值就行了.

C++ 实现中值滤波

我们来实现一下, 这方面还是能够找到不少结果的, 感觉这个博主写的还是很不错的,有兴趣的可以看下数字图像处理------中值滤波,还有图像处理之中值滤波介绍及C实现, 或者 中值滤波器(Median filter)特性及其实现, 这里我就不再造轮子了, 我们来看下 C++的实现
, 主要参考 第一篇文章, 可以看下效果

这里有一点点需要讨论的, 对于彩色图像的三个通道怎么处理, 自己的思路就是分成三个通道进行处理, 然后分别得到三个图之后进行合并三个通道, 得到结果图像. 查了下 目测大家都是这么做的, 可以看OpenCV 彩色图像的自适应中值滤波 C++ 和 彩色图像空间滤波(MATLAB) 这两篇文章, 思路都是一样的, 我们来实现一下.

//中值滤波:C++ 代码实现 // 处理单通道图像 // 参考 https://www.cnblogs.com/ranjiewen/p/5699395.html
cv::Mat medianFilterGray(const cv::Mat &src, int ksize = 3)
{cv::Mat dst = src.clone();//0. 准备:获取图片的宽,高和像素信息,const int  num = ksize * ksize;std::vector<uchar> pixel(num);//相对于中心点,3*3领域中的点需要偏移的位置int delta[3 * 3][2] = {{ -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, -1 }, { 0, 0 }, { 0, 1 }, { 1, -1 }, { 1, 0 }, {1, 1}};//1. 中值滤波,没有考虑边缘for (int i = 1; i < src.rows - 1; ++i){for (int j = 1; j < src.cols - 1; ++j){//1.1 提取领域值 // 使用数组 这样处理 8邻域值 不适合更大窗口for (int k = 0; k < num; ++k){pixel[k] = src.at<uchar>(i+delta[k][0], j+ delta[k][1]);}//1.2 排序  // 使用自带的库及排序即可std::sort(pixel.begin(), pixel.end());//1.3 获取该中心点的值dst.at<uchar>(i, j) = pixel[num / 2];}}return dst;
}

思路还是那个思路, 不过在写的过程中, 我在想, 能不能直接处理彩色的图像呢, 对于彩色图像最麻烦的地方就是排序了, 我们没办法考虑颜色的高低值, 所以 那我们自定义一个比较函数应该就行了吧. 我们使用三个颜色的和值 做比较
这里使用了C++ 的sort 自定义函数的方法, 这边采用的比较函数的方式, 还有别的方式实现两个元素的比较, 可以参考c++中vector自定义排序的问题

// 自定义两个像素的比较函数,  // 使用和值 排序
bool comp(const cv::Vec3b &p1, const cv::Vec3b &p2)
{return (p1[0] + p1[1] + p1[2]) < (p2[0] + p2[1] + p2[2]);
}
// 尝试彩色图像, 中值排序使用三个通道的和排序
cv::Mat medianFilterColor(const cv::Mat &src, int ksize = 3)
{cv::Mat dst = src.clone();//0. 准备:获取图片的宽,高和像素信息,const int  num = ksize * ksize;std::vector<cv::Vec3b> pixel(num);//相对于中心点,3*3领域中的点需要偏移的位置int delta[3 * 3][2] = {{ -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, -1 }, { 0, 0 }, { 0, 1 }, { 1, -1 }, { 1, 0 }, {1, 1}};//1. 中值滤波,没有考虑边缘for (int i = 1; i < src.rows - 1; ++i){for (int j = 1; j < src.cols - 1; ++j){//1.1 提取领域值 // 使用数组 这样处理 8邻域值 不适合更大窗口for (int k = 0; k < num; ++k){pixel[k] = src.at<cv::Vec3b>(i + delta[k][0], j + delta[k][1]);}//1.2 排序  // 使用自定义的排序函数排序彩色图像std::sort(pixel.begin(),pixel.end(),comp);//1.3 获取该中心点的值dst.at<cv::Vec3b>(i, j) = pixel[num / 2];}}return dst;
}

opencv 中值滤波

这里还是之前的方法, 一样的接口, 实现起来很简单, opencv 提供的 函数还是很丰富的, 很厉害

// opencv 中值滤波
cv::Mat mediaFilterDefault(const cv::Mat &src, int ksize = 3)
{cv::Mat dst;cv::medianBlur(src, dst, ksize);return dst;
}

中值滤波算法对比

我们这里就跟之前均值算法的计算很相似了, 我们已经写了三种算法的实现, 然后测试就好了, 趁着功夫, 将上一章一直重复的两个图比较并输出参数的部分写成了一个函数

// 对比两个图像 然后输出 参数信息
QString compareImages(const cv::Mat &I1,const cv::Mat &I2,const QString str = "noise",const QString str_temp = "image-%1: psnr:%2, mssim: B:%3 G:%4 R:%5")
{double psnr_ = getPSNR(I1, I2);cv::Scalar mssim_ = getMSSIM(I1, I2);// 根据 输出模板 生成参数信息QString res_str = str_temp.arg(str).arg(psnr_).arg(mssim_.val[0]).arg(mssim_.val[1]).arg(mssim_.val[2]);return res_str;// cv::imwrite(IMAGE_DIR + "dst_" + std::to_string(i + 1) + ".png", dst[i]);
}

没什么难度, 就是用来拼接一个字符串, 用来显示在界面上, 或者 输出输出来,

这样的我们就能很容易的去写测试的函数了, 三种方法依次去实现, 比较麻烦的是第一种, 需要将彩色图像分成三个通道的灰度图像, 然后分别进行中值滤波, 最后合并结果,得到结果图像.

void MainWindow::testFunc2(void)
{// 测试 中值 滤波 三种方式的不同const int TEST = 1; // 使用统一的图进行测试 暂时使用 高 椒盐噪声图像QString res_str;// 噪声图像的参数值res_str = compareImages(gSrcImg, gNoiseImg[TEST]);ui->pt_log->appendPlainText(res_str);cv::Mat test_img = gNoiseImg[TEST];cv::Mat dst[3];// 测试 中值滤波 拆分三个通道进行中值滤波然后合并图像std::vector<cv::Mat> bgr(3);cv::split(test_img, bgr);bgr[0] = medianFilterGray(bgr[0]);bgr[1] = medianFilterGray(bgr[1]);bgr[2] = medianFilterGray(bgr[2]);cv::merge(bgr, dst[0]);     // 第一种方式dst[1] = medianFilterColor(test_img);   // 第二种 彩色直接 计算中值滤波dst[2] = mediaFilterDefault(test_img);  // opencv 实现 中值滤波// 分别计算三种方式得到的滤波的效果 (结果图与 原始图比较)for(int i=0;i<3;i++){res_str = compareImages(gSrcImg, dst[i]);// 噪声的参数值ui->pt_log->appendPlainText(res_str);cv::imwrite(IMAGE_DIR + "dst_media_" + std::to_string(i+1)+".png",dst[i]);}
}

我们仍然选择高椒盐噪声图像用于测试, 先看下结果, 分别对应噪声图的参数, 以及三种方法进行的参数结果.
第三行的结果就是我们进行自定义排序的图像处理,

image-noise: psnr:19.4727, mssim: B:0.353134 G:0.383638 R:0.629353
image-noise: psnr:33.3725, mssim: B:0.896859 G:0.915976 R:0.912563
image-noise: psnr:31.2668, mssim: B:0.866162 G:0.901717 R:0.879337
image-noise: psnr:34.3125, mssim: B:0.902338 G:0.921419 R:0.91531

我们看一下结果图像, 原始图像可以看 https://gitee.com/schen00/BlogImage/raw/master/image/1588468343599.png 这里,

gitee 限制了 1M 以上的图的显示, 所以有需要的去看这个就好.

最近一直用的图拼接使用的 做好图 在线拼接图片 主要是懒得自己写了, http://www.zuohaotu.com/image-merge.aspx 链接在这里了 有需要自取

这里的第一副图是噪声图像, 第二副是我们拆分通道处理后拼接起来了的, 没有处理边缘的细节问题, 第三章图就是我们进行自定义中值排序得到的图, 部分点处理不掉 甚至还复制了出来, 不过整体效果还是不错的, 第四章图就是opencv 自带的中值滤波的处理.

中值滤波算法优化

类似均值滤波, 处理的时候考虑变化了的边界就好了, 那中值滤波怎么优化呢, 感觉这一块做的人还挺多, 中值滤波的优化主要是使用自适应中值滤波, 和在中值滤波的方法上进行加速运算,

自适应中值滤波

可以参考自适应中值滤波及实现, 我感觉介绍的还是比较详细的, 主要的思路就是如果噪声比较严重时, 窗口获取到的中值可能是噪声值, 这时候增大窗口, 然后重新进行中值滤波,直到找到比较符合的中值.
引用他给出的部分叙述

在自适应中值滤波算法中,A步骤里面会先判断是否满足 Zmin<Zmed<ZmaxZmin<Zmed<ZmaxZmin<Zmed<ZmaxZmin<Zmed<ZmaxZmin<Zmed<ZmaxZmin<Zmed<Zmax。这一步骤实质是判断当前区域的中值点是否是噪声点,通常来说是满足 Zmin<Zmed<ZmaxZmin<Zmed<ZmaxZmin<Zmed<ZmaxZmin<Zmed<ZmaxZmin<Zmed<ZmaxZmin<Zmed<Zmax 这个条件的,此时中值点不是噪声点,跳转到B;考虑一些特殊情况,如果 Zmed=ZminZmed=Zmin或者Zmed=ZmaxZmed=ZmaxZmed=ZminZmed=Zmin或者Zmed=ZmaxZmed=ZmaxZmed=ZminZmed=Zmin或者Zmed=ZmaxZmed=Zmax ,则认为是噪声点,应该扩大窗口尺寸,在一个更大的范围内寻找一个合适的非噪声点,随后再跳转到B,否则输出的中值点是噪声点;
接下来考虑跳转到B之后的情况:判断中心点的像素值是否是噪声点,判断条件为 Zmin<Zxy<ZmaxZmin<Zxy<ZmaxZmin<Zxy<ZmaxZmin<Zxy<ZmaxZmin<Zxy<ZmaxZmin<Zxy<Zmax,原理同上,因为如果Zxy=ZminZxy=ZminZxy=ZminZxy=ZminZxy=ZminZxy=Zmin或者Zxy=ZmaxZxy=ZmaxZxy=ZmaxZxy=ZmaxZxy=ZmaxZxy=Zmax,则认为是噪声点。如果不是噪声点,我们可以保留当前像素点的灰度值;如果是噪声点,则使用中值替代原始灰度值,滤去噪声。

同样的, 图像处理基础(2):自适应中值滤波器(基于OpenCV实现), 这篇文章写的更好一点, 并给出了 opencv 的实现代码, 我们来看一下

// 自适应中值滤波窗口实现  // 图像 计算座标, 窗口尺寸和 最大尺寸
uchar adaptiveProcess(const Mat &im, int row, int col, int kernelSize, int maxSize)
{std::vector<uchar> pixels;for (int a = -kernelSize / 2; a <= kernelSize / 2; a++)for (int b = -kernelSize / 2; b <= kernelSize / 2; b++){pixels.push_back(im.at<uchar>(row + a, col + b));}sort(pixels.begin(), pixels.end());auto min = pixels[0];auto max = pixels[kernelSize * kernelSize - 1];auto med = pixels[kernelSize * kernelSize / 2];auto zxy = im.at<uchar>(row, col);if (med > min && med < max){// to Bif (zxy > min && zxy < max)return zxy;elsereturn med;}else{kernelSize += 2;if (kernelSize <= maxSize)return adaptiveProcess(im, row, col, kernelSize, maxSize); // 增大窗口尺寸,继续A过程。elsereturn med;}
}
// 自适应均值滤波
cv::Mat adaptiveMediaFilter(const cv::Mat &src, int ksize = 3)
{int minSize = 3; // 滤波器窗口的起始尺寸int maxSize = 7; // 滤波器窗口的最大尺寸cv::Mat dst;// 扩展图像的边界cv::copyMakeBorder(src, dst, maxSize / 2, maxSize / 2, maxSize / 2, maxSize / 2, cv::BorderTypes::BORDER_REFLECT);// 图像循环for (int j = maxSize / 2; j < dst.rows - maxSize / 2; j++){for (int i = maxSize / 2; i < dst.cols * dst.channels() - maxSize / 2; i++){dst.at<uchar>(j, i) = adaptiveProcess(dst, j, i, minSize, maxSize);}}cv::Rect r = cv::Rect(cv::Point(maxSize / 2, maxSize / 2), cv::Point(dst.rows-maxSize / 2, dst.rows-maxSize / 2));cv::Mat res = dst(r);return res;
}

我们这里还是使用的分离三个通道然后进行自适应均值滤波, 参数就使用默认的3, 最大窗口设为7, 我们测试还是跑的之前的高椒盐噪声图像, 下面给出的最后一行就是我们使用自适应中值滤波得到的结果, 至少从 psnr 的参数上我们能看到图像质量的提升, 我们给出图像结果, 肉眼上能看出稍微一点的区别, 对比之前的已经完全不存在白点了, 图像已经比较接近真实图像了…

// 拆分三个通道 计算自适应中值滤波
cv::split(test_img, bgr);
for (int i = 0; i < 3; i++)bgr[i] = adaptiveMediaFilter(bgr[i]);
cv::merge(bgr, dst[3]);
image-noise: psnr:19.4727, mssim: B:0.353134 G:0.383638 R:0.629353
image-noise: psnr:33.3725, mssim: B:0.896859 G:0.915976 R:0.912563
image-noise: psnr:31.2655, mssim: B:0.86636 G:0.901517 R:0.879384
image-noise: psnr:34.3125, mssim: B:0.902338 G:0.921419 R:0.91531
image-noise: psnr:37.4024, mssim: B:0.946158 G:0.958146 R:0.953884

中值滤波计算加速

由于中值滤波无论多大的窗口都是用来将窗口内的像素进行排序, 这里的优化有两个方向 一个是窗口的优化, 一个计算的加速,

我真的 imageshop 的这篇文章 任意半径中值滤波(扩展至百分比滤波器)O(1)时间复杂度算法的原理、实现及效果。
已经写的比较完全了, 我都不想在写了,

再从中值滤波的快速算法 偷一张图,

感兴趣的可以看一下的链接
OpenCV源码分析(四):中值滤波 这里详细介绍了 opencv 中怎么实现的 中值滤波

总结

算是从中值滤波的基础上做了一个开始, 介绍了一下中值滤波的原理, 然后根据原理使用C++ 进行了实现, 之后再进行 opencv 的实现, 然后我们根据之前的程序上加入了中值滤波的实现效果, 最后在中值滤波的基础上进行优化, 做了自适应中值滤波的实现,测试发现结果还要更好, 最后我稍微提了一下中值滤波的优化加速, 这一块做的很多, 可以去参考里面去找, 算是完成了中值滤波的章节, 如果这里搞懂了我再来完善这一章节…

参考

  1. 《绘制函数调用图(call graph)(4):doxygen + graphviz_运维_许振坪的专栏-CSDN博客》. 见于 2020年5月2日. https://blog.csdn.net/benkaoya/article/details/79763668.
  2. 《任意半径中值滤波(扩展至百分比滤波器)O(1)时间复杂度算法的原理、实现及效果。 - Imageshop - 博客园》. 见于 2020年5月3日. https://www.cnblogs.com/Imageshop/archive/2013/04/26/3045672.html.
  3. 《数字图像处理------中值滤波 - ranjiewen - 博客园》. 见于 2020年5月2日. https://www.cnblogs.com/ranjiewen/p/5699395.html.
  4. 《【算法随记三】小半径中值模糊的急速实现(16MB图7.5ms实现) + Photoshop中蒙尘和划痕算法解读。 - Imageshop - 博客园》. 见于 2020年5月3日. https://www.cnblogs.com/Imageshop/p/11087804.html.
  5. 《图像处理基础(2):自适应中值滤波器(基于OpenCV实现) - Brook_icv - 博客园》. 见于 2020年5月3日. https://www.cnblogs.com/wangguchangqing/p/6379646.html.
  6. 《图像处理之原理 - 中值滤波 - tanfy - 博客园》. 见于 2020年5月2日. https://www.cnblogs.com/tanfy/p/median_filter.html.
  7. 《图像处理之中值滤波介绍及C实现 - 淇淇宝贝 - 博客园》. 见于 2020年5月2日. https://www.cnblogs.com/qiqibaby/p/5281743.html.
  8. 《中值滤波的快速算法_网络_LinJM-机器视觉-CSDN博客》. 见于 2020年5月3日. https://blog.csdn.net/linj_m/article/details/35780163.
  9. 《中值滤波器》. 收入 维基百科,自由的百科全书, 2017年9月8日. https://zh.wikipedia.org/w/index.php?title=%E4%B8%AD%E5%80%BC%E6%BB%A4%E6%B3%A2%E5%99%A8&oldid=46098815.
  10. 《中值滤波器(Median filter)特性及其实现_人工智能_Ivan 的专栏-CSDN博客》. 见于 2020年5月2日. https://blog.csdn.net/liyuanbhu/article/details/48502005.
  11. 《自适应中值滤波及实现_人工智能_hongbin_xu的博客-CSDN博客》. 见于 2020年5月3日. https://blog.csdn.net/hongbin_xu/article/details/79780967.
  12. GitHub. 《ARM-Software/ComputeLibrary》. 见于 2020年5月3日. https://github.com/ARM-software/ComputeLibrary.
  13. 《c++中vector自定义排序的问题_C/C++_Stone_Sky-CSDN博客》. 见于 2020年5月2日. https://blog.csdn.net/aastoneaa/article/details/8471722.
  14. 《OpenCV 彩色图像的自适应中值滤波 C++_人工智能_cyf15238622067的博客-CSDN博客》. 见于 2020年5月3日. https://blog.csdn.net/cyf15238622067/article/details/88718615.
  15. 《‪opencv: ‪Image Filtering》. 见于 2020年5月3日. http://schen.xyz:89/opencv/d4/d86/group__imgproc__filter.html#gad7c87bbc46b97e7eafa71357916ab568.
  16. 知乎专栏. 《OpenCV图像处理专栏九 | 基于直方图的快速中值滤波算法》. 见于 2020年5月3日. https://zhuanlan.zhihu.com/p/98092747.
  17. 简书. 《OpenCV源码分析(四):中值滤波》. 见于 2020年5月2日. https://www.jianshu.com/p/eb0b856286f2.

opencv-11-中值滤波及自适应中值滤波相关推荐

  1. OpenCV局部阙值分割的自适应阙值算法

    前言: 当图片中的照明出现不均匀的情况时,图像的灰度值就会出现灰度值不均匀,如果我们采用全局阙值分割,对所有像素值共用同一个阙值,往往无法得到理想的分割.而局部阙值分割则可以解决这个问题,它所提供的思 ...

  2. matlab编程实现自适应均值滤波和自适应中值滤波

    matlab编程实现自适应滤波器 一.自适应均值滤波器 1. 原理部分: 2. 程序代码 3. 结果对比 二.自适应中值滤波 1. 原理部分 2.程序代码 3. 结果对比 一.自适应均值滤波器 1. ...

  3. opencv(python)------二值化阙值(threshold)、自适应阙值(adaptiveThreshold)

    1. 简单阈值 对于每个像素,应用相同的阈值.如果像素值小于阈值,则将其设置为0,否则将其设置为最大值.函数cv.threshold用于应用阈值.第一个参数是源图像,它应该是灰度图像.第二个参数是阈值 ...

  4. 自适应中值滤波及实现

    前言 无意中看到了一篇比较老的论文,Adaptive median filters: new algorithms and results.感兴趣的可以下载下来看看.主要就是提出了一种自适应中值滤波算 ...

  5. input自适应_【正点原子FPGA连载】第十一章基于OV5640的自适应二值化实验-领航者ZYNQ之HLS 开发指南...

    1)摘自[正点原子]领航者ZYNQ之HLS 开发指南 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手 ...

  6. 【OpenCV 例程200篇】58. 非线性滤波—中值滤波

    [OpenCV 例程200篇]58. 非线性滤波-中值滤波 欢迎关注 『OpenCV 例程200篇』 系列,持续更新中 欢迎关注 『Python小白的OpenCV学习课』 系列,持续更新中 图像滤波是 ...

  7. 数字图像处理,自适应中值滤波的C++实现

    自适应中值滤波的原理 自适应中值滤波的思想是根据噪声密度改变滤波窗口的大小,同时对噪声点和信号点采取不同的处理方法.对噪声点进行中值滤波,对信号点保持其灰度值不变. 设为fij为点(i,j)的灰度值, ...

  8. OpenCV函数简记_第三章数字图像的滤波处理(方框,均值,高斯,中值和双边滤波)

    系列文章目录 OpenCV函数简记_第一章数字图像的基本概念(邻域,连通,色彩空间) OpenCV函数简记_第二章数字图像的基本操作(图像读写,图像像素获取,图像ROI获取,图像混合,图形绘制) Op ...

  9. matlab设计自适应中值滤波,matlab课程设计(自适应中值滤波).doc

    matlab课程设计(自适应中值滤波).doc 10信息工程系课程设计报告课程MATLAB课程设计专业通信工程班级2级本科二班学生姓名1景学号114学生姓名2学号1414学生姓名3王学号6学生姓名4学 ...

  10. matlab练习程序(自适应中值滤波RAMF)

    中值滤波是很经典的算法了.今天看论文又知道还有一种叫自适应中值滤波的算法RAMF.原论文在这里. RAMF主要通过以下两步来处理图像. 1.首先确定最大的滤波半径,然后用一个合适的半径r对图像进行滤波 ...

最新文章

  1. 计算机图形学入门总结!
  2. android电视盒子解码很慢,电视盒子反应慢又卡原因及解决办法推荐!
  3. intel服务器最新主板芯片组,intel主板芯片组的介绍
  4. Python 深浅copy 和文件操作
  5. Logistics模型预测银行贷款违约
  6. Power BI统一报表平台演示环境发布
  7. 找上海或深圳塑胶模具工作
  8. java 分级显示_上级部门与下级部门的分类显示
  9. centos时间同步
  10. Android的启动方式
  11. UrlRewrite 的配置和使用总结
  12. php汉字存储容量大小,存储400个24*24点阵汉字字形所需的存储容量是多少
  13. KMeans算法的Mapreduce实现
  14. JavaScript实现点赞效果
  15. 如何看电脑内存型号?
  16. 计算机语言解释方法,close
  17. Linux系列一 VMware 中 Fedora系统的安装与网络配置
  18. ATAT 报错Impossible to natch point correlations
  19. 无线可编程、兼具多功能的鼠标如何选?这里有你需要的答案
  20. 尚硅谷数据结构和算法01-数据结构介绍和稀疏数组

热门文章

  1. 抖音充值显示服务器繁忙是什么原因,为什么抖音充值总是失败呢
  2. 从今往后,我就是一名前端攻城狮
  3. 经典r-k法 matlab,解微分方程欧拉法,R-K法及其MATLAB实例
  4. 来看看你踩坑没有,新手做自媒体却没有收益?原因都在这5点
  5. java ee字体_JavaEE——CSS字体样式
  6. 如何用微信小程序,每天给自己赚个鸡腿?
  7. 基于GIS的三维智慧警务系统
  8. 程序员实习期馒头加酸菜,转正后月薪10K起步:走路都带风
  9. 全网把Map中的hash()分析的最透彻的文章,别无二家
  10. 大学英语六级超全复习资料