admin管理员组

文章数量:1544738

图像处理——去除图像上杂乱的干扰(庖丁解牛)

源码地址:图像处理——去除图像上杂乱的干扰

庖丁解牛

1. #include <opencv2/opencv.hpp>
2. #include <opencv2/highgui/highgui_c.h>
3. #include <iostream>

前三行是将库文件的头文件加载进来,头文件里包含着大量的声明,面向对象设计程序需要用到大量已经封装好的库函数,将头文件加载进来后才能有效调用这些库函数。其中,前两个是第三方库-计算机视觉开源库头文件,按理说包含第一个就可以,可是只包含第一个的话创建显示窗口的时候会报错,因此又加载了highgui模块,可能是我的环境变量搭建的有问题,但我不知道问题在哪。第三个是C++的标准输入输出流。

5. using namespace cv;
6. using namespace std;

声明使用标准命名空间,可不可以不声明标准命名空间?可以,但是,在后期编写程序的时候代码量写得繁琐,总是要写重复的东西。简单理解,命名空间就像一个屋子一样,里面有好多已经起好的名字,比如A屋里有张三李四王二麻子,要想准确的叫到A屋里的张三是不是要说:A屋里的张三过来一下。如果不加“A屋里的”限定 一下,是不是有可能别处的张三也跑过来了?如果不提前声明一下,是不是每次叫张三都需要带上“A屋里的”这几个字,是不是很麻烦?有一个简单的办法就是事先跟大家声明一下,我今天叫张三就是叫A屋里的张三,其他地方的张三不要过来,这样每次叫张三是不是就很简单了,叫一声张三他就跑过来了。

9. char filename[] = {
    0 };

定义一个char(字符型,character的缩写)类型数组来存储用户输入的图像存储路径。关于变量的类型:1.变量就相当于一个容器,什么样的容器就装什么东西,比如说用麻袋去装水显然就不合适。一种类型的变量就存储一类数据。2.定义变量就是告诉编译器我这个类型的容器有多大,有多大就需要给分配多大的空间,分配的少了将来有东西来了(值传递过来)就装不下了。

11. int main(int argc, char** argv){
   }

主函数main(),在这里主函数中定义了两个形参,其实在vs中运行程序不定义这两个形参也可以。用户定义的函数是被主函数调用,而主函数是被编译器或者说系统调用的。第一个形式参数是整型,用来记录向主函数中传递命令的个数。例如,使用cmd指令时,输入notepad后回车,系统只会自动打开记事本,相当于此时的argc=1,告诉主函数只传递过来了一个指令,以防把一个指令错读、拆分成两个指令或其他。
输入notepad && explorer后系统会打开记事本和资源管理器这两个应用程序,相当于此时的argc=2,告诉主函数传递过来了两个指令。
第二个参数char** argv 等价于char* argv[],即定义了一个指针数组,并且是char类型的。指针数组也是数组,不是指针。如果没有* 则argv存储的是字符,即一个字符数组,由于* 的优先级高,将argv 指定为指针数组,即存放字符或字符串地址的数组,例如在上例中,argv[0]存储的是notepad这个字符串的地址,argv[1]存储的是explorerd的地址,这样在访问时便可以通过地址来访问,访问效率高,计算开支小。

13. Mat src, dest, gray, binary;

定义了四个Mat类型的变量,分别表示源图像source、目标图像destination、灰度图像、二值图像。Mat类是OpenCV中定义好的数据结构类型(如果没有前面的命名空间声明此句需要写成cv::Mat src, dest, gray, binary;即用两个冒号运算符告诉编译器这个Mat是cv中定义的Mat),被称之为基本图像容器(早期版本的OpenCV中没有这一结构类型)。类是在c++中引入的概念,可以与c语言中的结构体进行一个对比,但是类里面的内容更加丰富。

13. cout << "----------------------------------------------------------------" << endl << endl;
14. cout << "Please enter a image path as follows and press Enter." << endl << endl;
15. cout << "Eg: F:/cvpicture/flower.png" << endl << endl;
16.cout << "ps: Image preview will automatically turn off after 30 seconds!" << endl << endl;
17. cout << "----------------------------------------------------------------" << endl;
18. cout << "Please enter the path:";

使用C++中的标准输出流cout向屏幕输出提示信息,<<可以理解为信息的流向。endl是C++中的标准换行符,相当于c语言中的\n,这样写的好处是保证了代码在不同系统平台间的良好迁移性,在windows平台下的换行符是\r\n,在Linux平台下的换行符是\n,切记换行符是系统平台特征,而不是某一语言的特征。

20. cin >> filename;

使用标准输入流向变量中输入内容,cin是C++中的标准输入流,能实现C语言中scanf的功能,但比scanf的功能更加强大一些。(ps:在C++中scanf是非标准库函数,如果想要使用scanf需要这样来写scanf_s()。)

//调用imread()函数读取图像
22. src = imread(filename);
定义:CV_EXPORTS_W Mat imread( const String& filename, int flags = IMREAD_COLOR );
/** @brief Loads an image from a file.
@anchor imread
The function imread loads an image from the specified file and returns it. If the 
image cannot be read (because of missing file, improper permissions, unsupported or invalid format), the function returns an empty matrix ( Mat::data==NULL ).
Currently, the following file formats are supported:
-   Windows bitmaps - \*.bmp, \*.dib (always supported)
-   JPEG files - \*.jpeg, \*.jpg, \*.jpe (see the *Note* section)
-   JPEG 2000 files - \*.jp2 (see the *Note* section)
-   Portable Network Graphics - \*.png (see the *Note* section)
-   WebP - \*.webp (see the *Note* section)
-   Portable image format - \*.pbm, \*.pgm, \*.ppm \*.pxm, \*.pnm (always 
supported)
-   PFM files - \*.pfm (see the *Note* section)
-   Sun rasters - \*.sr, \*.ras (always supported)
-   TIFF files - \*.tiff, \*.tif (see the *Note* section)
-   OpenEXR Image files - \*.exr (see the *Note* section)
-   Radiance HDR - \*.hdr, \*.pic (always supported)
-   Raster and Vector geospatial data supported by GDAL (see the *Note* section)
@note
-   The function determines the type of an image by the content, not by the file 
extension.
-   In the case of color images, the decoded images will have the channels stored 
in **B G R** order.
-   When using IMREAD_GRAYSCALE, the codec's internal grayscale conversion will be used, if available.
Results may differ to the output of cvtColor()
-   On Microsoft Windows\* OS and MacOSX\*, the codecs shipped with an OpenCV 
image (libjpeg, libpng, libtiff, and libjasper) are used by default. So, OpenCV can always read JPEGs, PNGs,and TIFFs. On MacOSX, there is also an option to use native MacOSX image readers. But beware that currently these native image loaders give images with different pixel values because of the color management embedded into MacOSX.
-   On Linux\*, BSD flavors and other Unix-like open-source operating systems, 
OpenCV looks for codecs supplied with an OS image. Install the relevant packages (do not forget the development files, for example, "libjpeg-dev", in Debian\* and Ubuntu\*) to get the codec support or turn on the OPENCV_BUILD_3RDPARTY_LIBS flag in CMake.
-   In the case you set *WITH_GDAL* flag to true in CMake and @ref 
IMREAD_LOAD_GDAL to load the image, then the [GDAL](http://www.gdal) driver will be used in order to decode the image, supporting the following formats: [Raster](http://www.gdal/formats_list.html),[Vector](http://www.gdal/ogr_formats.html).
-   If EXIF information are embedded in the image file, the EXIF orientation will be taken into account and thus the image will be rotated accordingly except if the flag @ref 
IMREAD_IGNORE_ORIENTATION is passed.
-   Use the IMREAD_UNCHANGED flag to keep the floating point values from PFM 
image.
-   By default number of pixels must be less than 2^30. Limit can be set using 
system variable OPENCV_IO_MAX_IMAGE_PIXELS
@param filename Name of file to be loaded.
@param flags Flag that can take values of cv::ImreadModes
*/

调用cv中的库函数(或称API接口)读入图像。根据函数的定义可以看到函数imread()的返回值是Mat类,所以定义了对应变量src来存储函数的返回值。im是image的缩写形式,这个函数有两个形参,翻译完定义后对其剖析一下。
接下来翻译一下看定义说了些什么(水平有限,不到之处欢迎交流):

简介:从一个文件中载入一幅图像

@anchor imread

  • 函数从指定的文件中载入一幅图像并将其返回,如果图像不能被读取(由于文件缺失,未得到许可,没有支持或有效的格式),该函数返回一个空的矩阵(Mat::data==NULL Mat的对象被赋值为空)。
    当前,支持以下文件类型:
    -Windows 位图:*.bmp, *.dib(无条件支持)
    -JPEG 文件:*.jpeg, *.jpg, *.jpe (看后面的注释部分)
    -JPEG 2000 文件:*.jp2(看后面的注释部分)
    -便携网络图片:*.png (看后面的注释部分)
    -WebP :*.webp(看后面的注释部分)
    -便携图像格式:*.pbm, *.pgm, *.ppm *.pxm, *.pnm (无条件支持)
    -PEM 文件:*.pfm(看后面的注释部分)
    -Sun rasters :*.sr, *.ras(无条件支持)
    -TIFF 文件:*.tiff, *.tif(看后面的注释部分)
    -OpenEXR 图像文件:*.exr (看后面的注释部分)
    -Radiance HDR :*.hdr, *.pic(无条件支持)
    -GDAL支持的格栅和矢量地理空间数据

注释:

  • -函数是通过内容判定一幅图像的类型,而不是通过文件扩展名。
  • -对于彩色图像,解过码的图像将按照B G R的通道顺序存储。
  • -使用IMREAD_GRAYSCALE(灰度模式读入)时,如果编解码器内部的灰度转换可以使用,则使用该模块将图像转化为灰度图像。该结果可能和使用cvtColor()函数输出的结果存在差异。
  • -在 Microsoft Windows* OS 和 MacOSX*这两个平台上,默认使用由OpenCV映像传送来的编解码器(libjpeg, libpng, libtiff, and libjasper)。因此,OpenCV总是可以读取JPEGs,PNGs,和 TIFFs格式的图像。在 MacOSX 平台上,也可以选择使用MacOSX自身的图像读取器。但是,需要注意的是:当前由于颜色管理器嵌入在MacOSX中,所以MacOSX中的图像加载器会给图像们赋上不同的值。
  • -在Linux*, BSD flavors以及其他像Unix一样的开源操作系统上,OpenCV使用由操作系统映像提供的编解码器。安装相关的安装包(在Debian* 和 Ubuntu*不要忘了开发文件,例如,“libjpeg-dev”)以得到编解码器的支持,或者在CMake中打开OPENCV_BUILD_3RDPARTY_LIBS flag。
  • -如果你在CMake中把 * WITH_GDAL * 标识设置成真,并且用@ref IMREAD_LOAD_GDAL去加载图像,那么GDAL(http://www.gdal)
    驱动器将被用来解码图像,支持下列格式:Raster,Vector.
  • -如果EXIF信息被嵌入到图像文件,EXIF方向信息将被考虑在内。因此,除非标识 @ref IMREAD_IGNORE_ORIENTATION已经通过,否则图像将被相应的旋转。
  • -使用IMREAD_UNCHANGED标识以保持PFM图像中的浮点值不发生改变。
  • -像素的默认值必须低于2^30,使用系统变量OPENCV_IO_MAX_IMAGE_PIXELS可以设置

本文标签: 庖丁解牛杂乱图像处理干扰图像