• openCV基础知识


     

    openCV主体分为5个模块:

    • CV图像处理函数和计算机视觉算法;
    • ML机器学习库,包含许多聚类和数据分析函数;
    • HighGUI图像和视频的输入输出; [分成三部分:硬件部分--摄像机;文件部分--载入并保存图像文件;图形用户界面部分--打开窗口并且图像显示在窗口中(为窗口加入鼠标或键盘响应) ]
    • CXCore一些基本数据结构和相关函数;
    • CvAux一些被淘汰的算法和函数,或者一些新的实验性的算法和函数。(CVCAM摄像机接口)

     

    细说HighGUI

    1.创建窗口,载入、显示图像

    • cvNamedWindow()函数,用于在屏幕上创建窗口来显示图像,函数的第一个参数指定了窗口标题,第二个参数定义了窗口属性(窗口大小之类的,设置为0窗口大小不变;设置为CV_WINDOW_AUTOSIZE,窗口根据图像自动进行拉伸、放缩。)
    • cvResizeWindow(const char* name,int width,int height) //调整窗口大小
    //所使用的窗口名称与各个窗口系统所使用的窗口句柄之间进行转换。 
    void* cvGetWindowHandle(const char* name); 
    const char* cvGetWindowName(void* window_handle); 
    • cvLoadImage()函数,通过文件名确定被加载文件的格式,并自动分配描述图像数据结构所需内存。函数执行完后,返回指针,指向描述该图像数据结构(IplImage)的内存块。 IplImage结构体,处理单通道,多通道,整型的,浮点型的等所有类型的图形文件。
      IplImage* cvLoadImage(const char* name,int iscolor=CV_LOAD_IMAGE_COLOR); 
      当打开 一幅图像时,cvLoadImage()并不分析扩展名,还是通过分析图像文件的前几个字节来确定图像的编码格式。 
      iscolor默认情况下:CV_LOAD_IMAGE_COLOR以每个通道8位,3个通道的形式被读入。(不管原图像是多少通道,强制转换为3通道) 
                        CV_LOAD_IMAGE_ANYEPTH来读入非8位的图像,保持原通道。 
                        CV_LOAD_IMAGE_GRAYSCALE强制转换为单通道。 
                      (CV_LOAD_IMAGE_COLOR|CV_LOAD_IMAGE_ANYDEPTH 读入16位的彩色图像。) 
                        CV_LOAD_IMAGE_UNCHANGED读入数据与原始数据通道数以及位数保持一致。 
      注意:cvLoadImage()读入失败时,并不会产生运行时错误,而是返回一个空指针。 
    • cvSaveImage(),保存图像。    
    int cvSaveImage(const char* filename,const CvArr* image); 
    第一个参数表示文件名,其中后缀部分用来指定图像存储的编码格式。 
    第二个参数指向要存储的图像数据。 
    存储成功返回1,失败返回0。 
    注:CvArr* 是C风格的,功能与面向对象中的基类类似。当看到CvArr*时,可以用IplImage*参数传入。 
    • cvShowImage(),显示图像,第一个参数确定在那个窗口显示图像,如果窗口被指定CV_WINDOW_AUTOSIZE,作为第二个参数,根据图像大小来调整窗口与其一致。
    • cvWaitKey()函数,使程序暂停,函数参数正数,暂停后继续;函数参数0或负数,等待用户操作,无限期等待,直到用户触发按键,不会自启动。
    cvWaitKey(0)//无限期等待,直到用户触发按键。 
    while(1){ 
    if(cvWaitKey(100)==27) break; 
    }//等待用户触发事件100ms,100ms内没触发,则继续循环;如果触发并且按下esc(ASCII为27),则退出循环。 
    • cvMoveWindow(const char* name,int x,int y);//将窗口移动到左上角为x,y的位置。 
    • cvReleaseImage()函数,释放为该图像文件所分配的内存。
    • cvDestoryWindow()函数,销毁显示图像的窗口(关闭窗口,并释放为窗口分配的存)。
    • cvDestroyAllWindows(),关闭所有窗口,并释放相关的内存空间。 
    • cvStartWindowThread(),创建一个线程用来自动更新窗口,以及处理窗口触发事件。返回值为0,表示没有创建出线程。

    2.鼠标事件

    3.视频处理

    • cvCreateFileCapture()函数,由参数确定要读入的AVI文件,返回一个指向cvCapture结构的指针对应到AVI文件的开头,cvCapture结构包含从摄像机或视频文件中读取帧的信息
      • //初始化CvCapture结构 
        CvCapture* cvCreateFileCapture(const char* filename); 
        CvCapture* cvCreateCameraCapture(int index); //参数设置为-1时,OpenCV会打开一个窗口让用户选择需要摄像机。   利用HighGUI模块,返回相同的cvCapture*指针,类似从视频流中获取帧的方法。Capture结构初始化后,从视频文件或摄像设备读入图像没区别。
        【opencv里面的CvCapture什么作用:一个获取视频的抽象接口结构.你可以理解为它能连接到摄像头,然后你想让摄像头做什么,都要用函数调用,它作为参数起到控制摄像头的作用;
        CvCapture * pCapture = NULL,这个是opencvc接口,建议使用c++接口,简单得多
        
        
    • 读视频
      • int cvGrabFrame(CvCapture* capture);    //成功返回1,失败返回0。复制到一个用户不可见的空间里。 
        IplImage* cvRetrieveFrame(CvCapture* capture);   //在使用cvGrabFrame()以后,可以用此函数cvRetrieveFrame()来处理cvGrabFrame()读入的数据,这个函数会对读入帧做所有必须的处理。并且返回IplImage*指针,该指针指向另一块内部内存空间。 
      • IplImage* cvQueryFrame(CvCapture* capture);  //实际上是cvGrabFrame()和cvRetrieveFrame()的一个组合,与cvRetrieveFrame()返回同样的指针。   
      • void cvReleaseCapture(CvCapture** capture); //退出循环体,释放CvCapture结构中分配的内存。cvCapture结构的指针,与cvLoadImage()不同,它是使用cvCapture结构中分配好的内存,所以不用通过cvReleaseImage()函数释放,cvCapture结构被释放后,内存空间就会被释放。
    • 查询,设置视频播放控制(滚动条)

      • double cvGetCaptureProperty(CvCapture* capture,int property_id); 
        int cvSetCaptureProperty(CvCaptuer* capture,int property_id,double value); 
        //与之配套的cvGetCaptureProperty()函数,这些函数允许我们设置cvCapture对象的各种属性。CV_CAP_PROP_POS_FRAMES,表示以帧数来设置读入位置,想通过视频长度比例来设置读入位置,可通过AVI_RATIO代替FRAMES来实现。

        cvCreateTrackbar(),设置滚动条名称,并确定滚动条的所属窗口。
    • 写视频
      • //首先创建一个CvVideoWriter结构(视频写入结构)。 
        CvVideoWriter* cvCreateVideoWriter( 
            const char* filename,//视频文件名 
            int fourcc,//视频编码格式 
            double fps,//帧率 
            CvSize frame_size,//每帧的大小 
            int is_color = 1//图像是否为彩色 
        ); 
        int cvWriterFrame(CvVideoWriter* writer,const IplImage* image);//视频写入结构建好之后,需调用cvWriterFrame()函数,通过传入两个指针,来写入文件。 
        void cvReleaseVideoWriter(CvVideoWirter** writer);//关闭写入结构。 

    4.不同图像格式之间的转换

    void cvConvertImage(const CvArr* src,CvArr* dst,int flags=0);//用于不同图像格式之间的转换。 
    src---源图像:可以是单个,3个,4个通道,也可以是8位或者浮点类型像素格式。 
    dst---目标图像:8位的单通道或者3个通道。 
    flags---可以垂直旋转图像。 

     

    图像处理

    • cvCreateImage(cvGetSize(image)IPL_DEPTH_8U,3),分配自己的图像结构空间,存储平滑处理后的图像;而cvCreateFileCapture()只为新来的分配空间并只分配一帧图像的空间。  【第一个参数说明了 cvGetSize(),说明了当前图像结构的大小,图像大小同image;第二个参数说明了各通道每个像素点的数据类型,通道为8位;第三个参数说明了通道总数。】
    • 对图像进行比例为2的放缩处理

      • assert(in->width%2==0&&in->heigth%2==0)  放缩处理:高度、宽度为原来一半。【openCV中的重要数据结构是以结构体的形式实现,并以结构体指针的形式传递。】

    1.cvSmooth(image,out,CV_GAUSSIAN,3,3) 图像的平滑处理(模糊处理,用来减少图像上的噪声或者失真:对每个像素周围3*3区域进行高斯平滑处理。

    void cvSmooth(const CvArr *src,CvArr *dst,intsmoothtype=CV_GAUSSIAN,int param1=3,int param2=0,double param3=0,double param4=0); 
    //src,dst平滑操作的输入图像和结果;param1-4这四个参数的含义取决于smoothtype的值。 
    这里smoothtype有如下值: 
    CV_BLUR    简单模糊   支持in place方式输入,Nc1,3 输入数据类型 8u,32f, 输出数据类型 8u,32f,对每个像素param1*param2邻域求和。并做缩放1/(param1*pararam2) 
    CV_BLUR_NO_SCALE  简单无缩放变换的模糊,不支持in place,Nc 1, 输入数据类型 8u 输出数据类型 16s或32f 对每个像素的param1*param2 邻域求和 
    CV_MEDIAN   中值模糊,不支持in place,NC1,3 输入数据类型 8u,输出数据类型 8u 对图像进行核大小为param1*param1的中值滤波 
    CV_GAUSSIAN  高斯模糊 支持 in place ,NC1,3 输入数据类型 8u,32f,输出数据类型8u或32f 对图像进行核大小为param1*param2的高斯卷积 
    CV_BILATERAL 双边滤波 不支持 in place ,NC1,3 输入数据类型 8u, 输出数据类型8u 应用双线性3*3滤波,颜色sigma=param1,空间sigma=param2 
    
    1.CV_BLUR所列举的simple blur是最简单的操作。 输出图像的每一个像素是窗口中输入图像对应像素的简单平均值。simple blur 支持1~4个图像通道。
    2.CV_BLUR_NO_SCALE与CV_BLUR(simple blur)本质上是相同的,但并没有计算其平均值的操作。因此,输入图像和结果图像必须有不同的数值精度,才能保证模糊操作不会导致错误溢出。支持8位的输入图像,结果图像的数据类型必须是IPL_DEPTH_16S - 有符号16位整型,或IPL_DEPTH_32S;支持32位浮点图像的输入,结果图像的数据类型是32位浮点型。不支持in place。 3.中值滤波器(CV_MEDIAN)将中心像素的正方形邻域内的每个像素值用中间像素值(不是平均像素值)替换,它可以用来处理单个通道、三个通道或者四个通道8位的图像,但是不支持in place。 4.高斯滤波(CV_GAUSSIAN)不是最快的,但是是最有用的。高斯滤波用卷积核与输入图像的每个点进行卷积,将最终计算结果之和作为输出图像的像素值。 回到函数中,在高斯模糊中,前两个参数代表滤波器窗口的宽度和高度,可选择的第三个参数代表高斯卷积核的sigma值(是最大宽度的四分之一)。如果第三个参数未指定,系统会根据窗口尺寸通过下面的方程来自动确定高斯核的各个参数。 σx=(nx/2-1)*0.30+0.80,nx=param1 σy=(ny/2-1)*0.30+0.80,ny=param2 如果用户希望高斯核不对称,那么可以引入第四个参数。这样,第三个和第四个参数分别为水平方向和垂直方向的sigma值。 如果第三个和第四个参数已经给出,但是前两个参数被设为0,那么窗口的尺寸会根据sigma值自动确定。 5.双边滤波是“边缘保留滤波”的图像分析方法中的一种,将它与高斯平滑对比后会更容易理解。进行高斯滤波的通常原因是真实图像在空间内的像素是缓慢变化的,因此临近点的像素变化不会很明显。但是随机的两个点就可能形成很大的像素差(也就是说空间上的噪声点不是互相联系的)。正是基于这一点,高斯滤波在保留信号的条件下减少噪声,遗憾的是这种方法在接近边缘处就无效了,在那你不希望像素与邻近像素相关。因此高斯滤波会磨平边缘。而双边滤波能够提供一种不会将边缘的平滑掉的方法,但是需要更多的处理时间。 双边滤波会依据每个像素及其邻域构造一个加权平均值,加权计算包括两个部分,其中的一部分加权方式与高斯平滑的相同,第二部分也属于高斯加权,但不是基于中心像素点与其他像素点的空间距离之上的加权,而是基于其他像素与中心像素的亮度差值的加权。可以将双边滤波视为高斯平滑,对于相似的像素赋予较高的权重,不相似的像素赋予较小的权重。这种滤波的典型效果就是使处理过的图像看上去像是一幅源图的水彩画。 双边滤波含有两个参数。第一个参数代表空域中所使用的高斯核的宽度,与高斯滤波的sigma参数类似。第二个参数代表颜色域内高斯核的宽度。第二个参数越大,表明待滤波的强度(或颜色)范围越大(因此不连续的程度越高,以便保留)。

    2.图像形态学

    • cvErode()和cvDilate()---基本转换:膨胀与腐蚀,它们能实现多功能:如消除噪声,分割出独立的图像元素以及在图像中连接相邻元素。
      • void cvErode( const CvArr* src, CvArr* dst, IplConvKernel* element CV_DEFAULT(NULL), int iterations CV_DEFAULT(1) )// 腐蚀.是膨胀的反操作,求局部最小的操作,通常是用来消除图像中“斑点”噪声的。 /亮的区域被隔离和缩小。 element为核默认为3*3,iterations为迭代次数 
        void cvDilate( const CvArr* src, CvArr* dst, IplConvKernel* element CV_DEFAULT(NULL), int iterations CV_DEFAULT(1) ) //膨胀. 指将一些图像与核进行卷积。核可以视为模板或掩码,膨胀是求局部最大值的操作。/亮的区域得到了扩展和连接。
    • 核的自定义 cvCreateStructuringElementEx()
      • IplConvKernel*  cvCreateStructuringElementEx( int cols, int rows, int anchor_x, int anchor_y, int shape, int* values CV_DEFAULT(NULL) ) 
        //核的大小cols * rows ,核的参考点为(anchor_x ,anchor_y) , shape为形状, values 指针为指向填充核的数据区(当且仅当shape为CV_SHAPE_CUSTOM时起作用 ,若values为NULL, 则填充的核全为非0值) 
        shape参数为: 
            CV_SHAPE_RECT      //矩形 
            CV_SHAPE_CROSS   //十字形 
            CV_SHAPE_ELLIPSE //内接椭圆,(内部填充为1) 
            CV_SHAPE_CUSTOM //自定义型 
        void  cvReleaseStructuringElement( IplConvKernel** element ) //释放 
    • 更通用的形态学---在处理布尔图像和图像掩码时,基本的腐蚀和膨胀足够,但是对于处理灰度和彩色图像时,需要一些额外的操作。
      • CVAPI(void) cvMorphologyEx( const CvArr* src, CvArr* dst, CvArr* temp, IplConvKernel* element, int operation, int iterations CV_DEFAULT(1) )
        //temp为数组,它的操作如下,使用该数组时,应与源图像同样大小;element为核,operator指定形态学操作的方法,iterators为迭代次数 CV_MOP_OPEN开运算:先将其腐蚀,再膨胀/消除了高于其临近点的孤立点/*去除小的明亮区域,并且剩余的明亮区域被隔绝,其大小不变*/ CV_MOP_CLOSE闭运算:先将其膨胀,再腐蚀(用来去除噪声引起的区域)/消除了低于其临近点的孤立点/*亮的区域连在一起*/,但他们的基本大小不变 CV_MOP_GRADIENT形态梯度:gradient(src)=dilate(src)-erode(src)/*边缘以高亮区域突出*/描述图像亮度变化的剧烈程度 CV_MOP_TOPHAT礼帽:TopHat(src)=src-open(src)(A-A的开运算),开运算的结果是放大裂缝或局部低亮度区域/减去之后可以/*突出比A的周围区域更明亮的区域*/,并跟核大小有关。局部亮度极大点被分割 CV_MOP_BLACKHAT黑帽:BlackHat(src)=close(src)-src(B的闭运算-B)/*突出比B的周围区域更黑暗的区域*/

    3.漫水填充算法,标记或分离图像的一部分,以便进行下一步处理或分析

      • cvFloodFill(IplImage* img, CvPoint seedPoint, CvScalar newVal,cvScalar loDiff=cvScalarAll(0), cvScalar upDiff=cvScalarAll(0), CvConnectedComp* comp=NULL,int flags=4, CvArr* mask = NULL)
        //img指输入图像, seedPoint指种子像素坐标,newVal指用来填充区域的新颜色(像素被染色的值),loDiff和upDiff分别指与种子像素的值的上下差值,com指填充的联通域信息指针,其成员变量包括面积大小和平均颜色等信息。
        flags是关键参数,它包含了填充的几种方式选择,如邻哉是4联通还是8联通,是否只填充掩码矩阵,以及掩码矩阵的掩码值(默认为1)。参数包含CV_FLOODFILL_FIXED_RANGE,这时每个像素点都将与种子点比较而不是相邻点比较。
        mask为掩码矩阵,它是即是一个输入参数也是一个输出参数。mask作为输入时只有掩码值为0的像素点有效,而输出时有填充的像素的坐标点上也相应的被掩码(掩码值由flags决定,默认为1)。 

    4.尺寸调整

    5.图像金字塔 

    • 图像金字塔是一个图像集合,集合中所有的图像都源于同一个原始图像,而且是通过对原始图像连续采样获得,直到达到某个中止条件才停止降采样。(当然,降为一个像素肯定是中止条件。)有两种:高斯金字塔(向下降采样图像)和拉普拉斯金字塔(向上采样)。要从金字塔第i层生成第i+1层(我们表示第i+1层为Gi+1),我们先要用高斯核对Gi进行卷积,然后删除所有偶数行和偶数列。当然,新得到的图像面积会变为源图像的四分之一。按上述过程对输入图像循环执行操作就可产生整个金字塔。
      • void cvPyrDown( IplImage* src, IplImage* dst,IplIter filter= IPL_GAUSSIAN_5x5);//高斯金字塔 
        void cvPyrUp( IplImage* src, IplImage* dst,IplIter filter= IPL_GAUSSIAN_5x5); //拉普拉斯金字塔 
        函数PyrUp并不是函数PyrDown的逆操作。之所以这样是因为PyrDown是一个会丢失信息的函数。为了恢复原来(更高的分辨率)的图像,我们需要获得由降采样操作丢失的信息,这些数据形成了拉普拉斯金字塔。
        利用金字塔实现图像分割,图像分割需要先建立一个图像图像金字塔,然后在Gi的像素和Gi+1的像素直接依照对应关系,建立起“父-子”关系。通过这种方式,快速初始化分割可以先在金字塔高层的低分辨率图像上完成,然后逐层对分割加以优化。
    •  金字塔方法的图像分割
      • void cvPyrSegmentation( IplImage* src, IplImage* dst,CvMemStorage* storage, CvSeq** comp,int level, double threshold1, double threshold2 ); 
        src,输入图像;dst,输出图像;storage,存储连通部件的序列结果;comp,分割部件的输出序列指针 components; level,建立金字塔的最大层数 ;threshold1,建立连接的错误阈值 ;threshold2,分割簇的错误阈值 
        金字塔建立到 level 指定的最大层数。如果 p(c(a),c(b))<threshold1,则在层 i 的象素点 a 和它的相邻层的父亲象素 b 之间的连接被建立起来, 定义好连接部件后,它们被加入到某些簇中。如果p(c(a),c(b))<threshold2,则任何两个分割 a 和 b 属于同一簇。 
        如果输入图像只有一个通道,那么 p(c1,c2)=|c1-c2|. 如果输入图像有单个通道(红、绿、兰),那么p(c1,c2)=0,3·(c1r-c2r)+0,59·(c1g-c2g)+0,11·(c1b-c2b) . 每一个簇可以有多个连接部件。
        图像 src 和 dst 应该是 8-比特、单通道 或 3-通道图像,且大小一样.关于src和dst,需要特别注意一点:由于图像金字塔各层的长和宽都必须是整数,所以必须要求起始图像的长和宽都能够被2整除,并且能够被2整除的次数不少于金字塔总的层数。 
        指针storagee用来指向opencv的存储区。第8章将详细讨论此内容,但是现在应该知道一点,以下命令可以分配存储区域: CvMemStorage * storage=cvCreateMemStorage(); 
        comp参数用于存储分割结果更详细的信息--存储区里一系列相连的组成部分。具体工作机制将在第8章详细讲解。 

    6.阈值化 

    •  完成许多处理步骤之后,通常希望对图像中的像素做出最后的决策,或直接剔除一些低于或高于一定值的像素。在OpenCV中,函数cvThreshold()可以实现。其基本思想是,给定一个数组和一个阈值,然后根据数组中的每个元素是低于还是高于阈值而进行一些处理。 函数 cvThreshold 对单通道数组应用固定阈值操作。该函数的典型应用是对灰度图像进行阈值操作得到二值图像。(cvCmpS 也可以达到此目的) 或者是去掉噪声,例如过滤很小或很大象素值的图像点。本函数支持的对图像取阈值的方法由 threshold_type 确定.
      • void cvThreshold( const CvArr* src, CvArr* dst, double threshold, double max_value, int threshold_type ); 
        src:原始数组 (单通道 , 8-bit of 32-bit 浮点数)。 
        dst:输出数组,必须与 src 的类型一致,或者为 8-bit。每个阈值类型对应于一个特定的比较操作,该比较操作在源图像第i个像素和阈值之间进行。根据源图像的像素和阈值之间的关系,目标图像的像素dst可能被设置为0,src或max_value。 
        threshold:阈值 
        max_value:使用 CV_THRESH_BINARY 和 CV_THRESH_BINARY_INV 的最大值。 
        threshold_type:阈值类型 threshold_type=CV_THRESH_BINARY: 
        如果 src(x,y)>threshold 0,dst(x,y) = max_value, 否则.threshold_type=CV_THRESH_BINARY_INV: 
        如果 src(x,y)>threshold,dst(x,y) = 0; 否则,dst(x,y) = max_value. threshold_typ 
        //cvThreshold中阈值类型选项和对应的操作 
        阈值类型                             操作 
        CV_THRESH_BINARY             dst=(src>T)? M:0 
        CV_THRESH_BINARY_INV         dst= (src>T )  ? 0:M 
        CV_THRESH_TRUNC              dst = (src>T) ?M:src 
        CV_THRESH_TOZERO_INV         dst = (src > T)? 0:src 
        CV_THRESH_TOZERO             dst = (src >T) ?src:0 
        //自适应阈值:这是一种改进了的阈值技术,其中阈值本身是一个变量。 
        void cvAdaptiveThreshold(CvArr* src, CvArr* dst, double max_val, int adaptive_method=CV_ADAPTIVE_THRESH_MEAN_C, 
        int threshold_type=CV_THRESH_BINARY, int block_size=3, double param1=5); 
        cvAdaptiveThreshold有两种不同的自适应阈值方法,可以用参数adaptive_method进行设置。在这两种情况下,自适应阈值T(x,y)在每个像素点都不同。通过计算像素点周围的bxb区域的加强平均,然后减去一个常数来得到自适应阈值,b由参数block_size指定,常数由param1指定。如果使用CV_ADAPTIVE_THRESH_MEAN_C方法,那么对区域的所有像素平均加权。如果使用了CV_ADAPTIVE_THRESH_GAUSSIAN_C方法,那么区域中的(x,y)周围的像素根据高斯函数按照它们离中心的距离进行加权计算。最后参数threshold_type和前面的cvThreshold的参数一样。 
        针对有很强照明或反射梯度的图像,需要根据梯度进行阈值化时,自适应阈值技术非常有用。次函数只能处理单通道8位图像或浮点图像,它要求源图像和目标图像不能使用同一图像。 

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    1. main()的参数,argc和argv的说明

        argc和argv这两个参数一般在用命令行编译程序时有用,int类型的argc,用来统计程序运行时发送给main函数的命令行参数的个数,char *类型的argv[],为字符串数组,用来存放指向的字符串擦数的指针数组,每个元素指向一个参数。各成员含义:
        - argv[0]指向成员运行的全路径名,
        - argv[1 ]指向在dos命令行中执行程序名后的第一个字符串,
        - argv[2 ]指向执行程序名后的第二个字符串,
        - argv[3 ]指向执行程序名后的第三个字符串
        - ……
       如果有多个字符串,则用空格隔开,argv[0]不需要输入,命令参数中的值从argv[1 ]开始。—— 《opencv3编程入门》

    如何书写矩阵,以及矩阵数据的存取

    [1]

    Mat(int rows, int cols, int type);   //cvMat,函数的一种,矩阵变换函数
    // (_type is CV_8UC1,CV_64FC3, CV_32SC(12) etc.)

    CV_<bit_depth>(S|U|F)C<number_of_channels>

    1--bit_depth---比特数---代表8bite,16bites,32bites,64bites---举个例子吧--比如说,如
            如果你现在创建了一个存储--灰度图片的Mat对象,这个图像的大小为宽100,高100,那么,现在这张   
            灰度图片中有10000个像素点,它每一个像素点在内存空间所占的空间大小是8bite,8位--所以它对
            应的就是CV_8
         2--S|U|F--S--代表---signed int---有符号整形
                   U--代表--unsigned int--无符号整形
                   F--代表--float---------单精度浮点型
         3--C<number_of_channels>----代表---一张图片的通道数,比如:
             1--灰度图片--grayImg---是--单通道图像
             2--RGB彩色图像---------是--3通道图像
             3--带Alph通道的RGB图像--是--4通道图像

    e.g.  Mat rawImg(600, 500, CV_8U, Scalar(0))  //这个Scalar函数有啥作用呢?scalar -标量,是将图像设置成单一灰度和颜色
    //对于彩色图像:Scalar(255, 0, 0)-blue;calar(0,255, 0)-green;calar(0, 0, 255)-red;
    //对于灰度图像:Scalar(0)-全黑;scalar(255)-全白
    OpenCV:Mat元素的访问方法

    (1)使用Mat的成员函数at<>()
      // at()函数的声明
    template<typename _Tp> _Tp& at(int i0, int i1);
    使用at<>()函数来索引访问矩阵元素:
        Vec3b pix;  
        for (int r = 0; r < im.rows; r++)  
        {  
          for (int c = 0; c < im.cols; c++)  
          {     
            //根据矩阵元素类型和通道数来确定at函数传递的类型,这里使用的是Vec3b这个元素类型。之所以采用这个类型来接受at的返回值,是因为,我们的矩阵im是3通道,unsigned char类型的。
    pix
    = im.at<Vec3b>(r,c);
    pix = pix*scale; om.at<Vec3b>(r,c) = pix; } }

    (2)使用Mat的成员函数ptr<>()

    //ptr()函数声明
    template<typename _Tp> _Tp* ptr(int i0=0);
    使用at<>()函数来索引访问矩阵元素:
        Vec3b *ppix_im(NULL);  
        Vec3b *ppix_om(NULL);  
        for (int r = 0; r < im.rows; r++)  
        {  
          ppix_im = im.ptr<Vec3b>(r);  
          ppix_om = om.ptr<Vec3b>(r);  
          for (int c = 0; c < im.cols; c++)  
          {  
             ppix_om[c] = ppix_im[c]*scale;  
          }  
        }  

    (3)使用迭代器

    这里使用的迭代器是OpenCV自己定义的:
        MatIterator_<Vec3b> it_im, itEnd_im;  
        MatIterator_<Vec3b> it_om;  
        it_im    = im.begin<Vec3b>();  
        itEnd_im = im.end<Vec3b>();  
        it_om    = om.begin<Vec3b>();  
        for (; it_im != itEnd_im; it_im++, it_om++)  
        {  
          *it_om = (*it_im)*scale;  
        }  
    
    

    (4)使用Mat_简化索引

    Mat_这个类的元素访问比较容易一点,把原Mat类的对象可以直接赋值给Mat_对象:
        Mat_<Vec3b> im_, om_;  
        im_ = im;  
        om_ = om;  
        for (int r = 0; r < im.rows; r++)  
        {  
          for (int c = 0; c < im.cols; c++)  
          {  
            om_(r,c) = im_(r,c) * scale;  
          }  
        }  

    (5)使用OpenCV原有的实现

    om = im*scale; 

     [2]

    void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0)  //颜色空间转换
    • src: 输入图像
    • dst: 输出图像
    • code: 颜色空间转换标识符
      • OpenCV2的CV_前缀宏命名规范被OpenCV3中的COLOR_式的宏命名前缀取代
      • 注意RGB色彩空间默认通道顺序为BGR
      • 具体可以参考: enum cv::ColorConversionCodes部分
    • dstCn: 目标图像的通道数,该参数为0时,目标图像根据源图像的通道数和具体操作自动决定

     [3]    http://blog.csdn.net/xidiancoder/article/details/50864195  绘图(圆/椭圆)

     

    cvFloodFill(IplImage* img, CvPoint seedPoint, CvScalar newVal,cvScalar loDiff=cvScalarAll(0), cvScalar upDiff=cvScalarAll(0), CvConnectedComp* comp=NULL,int flags=4, CvArr* mask = NULL)//各参数的意义为:img指输入图像, seedPoint指种子像素坐标,newVal指用来填充区域的新颜色(像素被染色的值),loDiff和upDiff分别指与种子像素的值的上下差值,com指填充的联通域信息指针,其成员变量包括面积大小和平均颜色等信息。flags是关键参数,它包含了填充的几种方式选择,如邻哉是4联通还是8联通,是否只填充掩码矩阵,以及掩码矩阵的掩码值(默认为1)。参数包含CV_FLOODFILL_FIXED_RANGE,这时每个像素点都将与种子点比较而不是相邻点比较。mask为掩码矩阵,它是即是一个输入参数也是一个输出参数。mask作为输入时只有掩码值为0的像素点有效,而输出时有填充的像素的坐标点上也相应的被掩码(掩码值由flags决定,默认为1)。 

  • 相关阅读:
    leetcode Power of Two
    Lowest Common Ancestor of a Binary Search Tree
    Lowest Common Ancestor of a Binary Tree
    leetcode Delete Node in a Linked List
    leetcode Search a 2D Matrix II
    leetcdoe Valid Anagram
    leetcode Add Digits
    leetcode Single Number III
    leetcode Ugly Number
    leetcode Ugly Number II
  • 原文地址:https://www.cnblogs.com/Jessica-jie/p/7841323.html
Copyright © 2020-2023  润新知