[OpenCV]随笔记录

本文介绍了OpenCV中的图像大小调整方法,包括resize函数和图像金字塔(pyrDown, pyrUp)。resize可以改变图像为任意尺寸,而图像金字塔保持长宽比,适用于比例缩放。此外,文章还提到了cvWaitKey函数的使用以及一些基础结构如CvPoint和CvScalar。" 103880109,9202754,ES6模块化详解:导出与导入,"['JavaScript', 'ES6', '模块化']
摘要由CSDN通过智能技术生成

在实验室里听一点记一点,到时候再总结整理吧。先记下来再说。

一定要记住的page:http://wiki.opencv.org.cn/index.php/%E9%A6%96%E9%A1%B5


#include <highgui.h>

int main()

{
     IplImage * test=NULL;
     test = cvLoadImage ("D:\\demo.jpg");
     cvNamedWindow("test_demo",1);
	 cvMoveWindow("test_demo",800,10);
     cvShowImage("test_demo",test);
     cvWaitKey(0);
     cvDestroyWindow("test_demo");
     cvReleaseImage(&test);
     return 0;
}

已知函数:

1.IplImage *p=NULL;定义图像指针

IplImage是一个类,它包含以下结构:

typedef struct _IplImage
    {
        int  nSize;         /* IplImage大小,=sizeof(IplImage)*/
        int  ID;            /* 版本 (=0)*/
        int  nChannels;     /* 大多数OPENCV函数支持1,2,3 或 4 个通道 */
        int  alphaChannel;  /* 被OpenCV忽略 */
        int  depth;         /* 像素的位深度: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U,
                               IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F 可支持 */
        char colorModel[4]; /* 被OpenCV忽略 */
        char channelSeq[4]; /* 被OpenCV忽略 */
        int  dataOrder;     /* 0 - 交叉存取颜色通道,对三通道RGB图像,像素存储顺序为BGR BGR BGR ... BGR;
                                     1 - 分开的颜色通道,对三通道RGB图像,像素存储顺序为RRR...R GGG...G BBB...B。
                                  cvCreateImage只能创建交叉存取图像 */
        int  origin;        /* 0 - 顶—左结构,
                               1 - 底—左结构 (Windows bitmaps 风格) */
        int  align;         /* 图像行排列 (4 or 8). OpenCV 忽略它,使用 widthStep 代替 */
        int  width;         /* 图像宽像素数 */
        int  height;        /* 图像高像素数*/
        struct _IplROI *roi;/* 图像感兴趣区域. 当该值非空只对该区域进行处理 */
        struct _IplImage *maskROI; /* 在 OpenCV中必须置NULL */
        void  *imageId;     /* 同上*/
        struct _IplTileInfo *tileInfo; /*同上*/
        int  imageSize;     /* 图像数据大小(在交叉存取格式下imageSize=image->height*image->widthStep),单位字节*/
        char *imageData;  /* 指向排列的图像数据 */
        int  widthStep;   /* 排列的图像行大小,以字节为单位 */
        int  BorderMode[4]; /* 边际结束模式, 被OpenCV忽略 */
        int  BorderConst[4]; /* 同上 */
        char *imageDataOrigin; /* 指针指向一个不同的图像数据结构(不是必须排列的),是为了纠正图像内存分配准备的 */
    }
    IplImage;

每定义一个IplImage指针,就定义了一个矩形,矩形的每一行依次为nsize,ID……等等。如图:




2.cvLoadImage()


cvLoadImage( filename, -1 ); 默认读取图像的原通道数,filename为图像路径
cvLoadImage( filename, 0 ); 强制转化读取图像为灰度图
cvLoadImage( filename, 1 ); 读取彩色图


3.cvNameWindow("Image",1);命名图像空间


int cvNamedWindow( const char* name, int flags=CV_WINDOW_AUTOSIZE );
函数cvNamedWindow创建一个可以放置图像的窗口.
被创建的窗口可以通过它们的名字被引用.
如果已经存在这个名字的窗口,这个函数将不做任何事情.
若为0表示以固定尺寸显示,此时可以用cvResizeWindow控制窗口大小,这时图像根据窗口大小进行调整,且全铺在窗口上。可以用鼠标拉伸。
若为1,窗口以图像大小进行调整(即使先前设置过窗口大小),也会根据图像大小进行调整,且不可拉伸。

***使用了这个函数后,即使没有图像指针,在编译完成后也会生成一个窗口(灰色)。


关于cvResizeWindow(需要注意,这个函数是用来改变窗口大小的,而非改变图像大小。之所以看似图像大小也改变了,实际上是因为在NamedWindow参数里,设置为图像根据窗口进行调整。换句话说,它的原理是通过改变窗口大小——让图像跟着窗口变化——进而改变图像大小,而非直接改变图像大小。)


void cvResizeWindow( const char* name, int width, int height );

name 
将被设置窗口的名字。
width 
新的窗口宽度。
height 
新的窗口高度。

函数cvResizeWindow改变窗口的大小。


如果想要直接改变图像大小,需要resize函数或者图像金字塔pyrDown,pyrUp(不改变长宽比,一次面积放大4倍或者缩小4分之一)


以下为转载:

*************************************

OpenCV改变图像大小的操作有两类:resize与图像金字塔,但是这两类操作差别还是比较大的。

resize

函数原型

void resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR )

各个参数的意义比较直观,但是需要注意的是dsizefxfy必须不能同时为零,也就是说要么dsize不为零而fxfy同时可以为0,要么dsize0fxfy不同时为0resize函数的目标大小可以是任意的大小,可以不保持长宽比率,删除的像素或者新增的像素值通过interpolation(内插)控制;

 

图像金字塔

pyrDownpyrUp分别表示向下降采样与向上升采样,但是二者并不是互为逆操作;

void pyrDown(InputArray src, OutputArray dst, const Size& dstsize=Size(), int border-

Type=BORDER_DEFAULT )

void pyrUp(InputArray src, OutputArray dst, const Size& dstsize=Size(), int border-

Type=BORDER_DEFAULT )

这两个操作实现图像金字塔的经典操作,他们仅仅是分别代表一次采样操作,也就是说,向下(或者向上)进行相邻层次的金字塔采样,调用一次pyrDown函数只能降低到原图像尺寸的1/2;反之,调用pyrUp目标图像则为原图像尺寸的2倍。因为它们内部都给定了一次采样尺寸的约束。也就是说采样之后,长宽比基本是不变的。


void ResizeDemo()
{
         Mat img1=imread("person_org.jpg");
         Mat img2;
//将原图像变为32*32,长宽比被改变了
         resize(img1,img2,Size(32,32),0,0,CV_INTER_LINEAR);
         namedWindow("WindowOrg");
         namedWindow("WindowNew");
         imshow("WindowOrg",img1);
         imshow("WindowNew",img2);
 
         waitKey(10000);
}

#include <stdafx.h>
#include <highgui.h>
#include <cv.h>

int main()
{
	IplImage *Image;
	IplImage *NewImage;
	Image = cvLoadImage("D:\\1234.jpg",1);

	CvSize sz;
	sz = cvGetSize(Image);
	sz.height /= 2;
	sz.width /= 2;
	//if pyrup,
	//sz.height*=2;
	//sz.width*=2;
	//setting height and width.

	NewImage = cvCreateImage(sz,IPL_DEPTH_8U, 3);
	//Create Image

	cvPyrDown(Image, NewImage, 7);
	//cvPryup(Image,NewImage,7);
	//若使用这个函数,需要事先建立好一个尺寸为原图一半的图并用IplImage指针指向它.7相当于CV_GAUSSIAN_5x5.

	cvNamedWindow("graph1", 1);
	cvNamedWindow("graph2", 1);
	cvShowImage("graph1", Image);
	cvShowImage("graph2", NewImage);
	cvWaitKey(0);
	cvDestroyAllWindows();
	return 0;
}

总结:resize可以一次性将原图像变为任意不为0的尺寸,适合用来做归一化图像操作;而pyrDown与pyrUp适合做长宽比率不变得操作,且调用一次只能长和宽只能变为原来的1/2或者2倍,也即是说面积变为原来的1/4或者4倍。

转载自http://blog.sina.com.cn/s/blog_4b0020f30101cgok.html


**********************************************



4.void cvShowImage( const char* name, const CvArr* image );


Example:
cvShowImage("Image",p);
函数cvShowImage 在指定窗口中显示图像.如果窗口创建的时候被设定标志CV_WINDOW_AUTOSIZE,
那么图像将以原始尺寸显示;否则,图像将被伸缩以适合窗口大小.

一条语句只显示一次图像,若后面的语句没有cvWaitKey(0)的话,图像一闪而过。


5.cvWaitKey(delay)


Example:
cvWaitKey(0);
函数的功能是不断刷新图像,频率时间为delay,单位为ms。

delay为<=0时,无限制等待按键。按键后(在显示出的图片里进行按键),才执行WaitKey之后的语句。另外注意WaitKey单位为毫秒!它的功能可以理解为延时X毫秒后,执行接下来的语句。

函数cvWaitKey无限制的等待按键事件(delay<=0时);或者延迟"delay"毫秒。返回值为被按键的值,如果超过指定时间则返回-1。


6.void cvDestroyWindow( const char* name );


Example;
cvDestroyWindow("Image");
销毁指定窗口


7.cvReleaseImage(&p);//销毁指针


cvReleaseImage函数只是将IplImage*型的变量值赋为NULL,而这个变量本身还是存在的并且在内存中的存储位置不变


8.void cvMoveWindow( const char* name, int x, int y );


设定窗口的位置。
name 将被设置的窗口的名字。
x 窗口左上角的x坐标。
y 窗口左上角的y坐标。
函数cvMoveWindow改变窗口的位置。


cvActionTargetMod()
Example:
 cv Get 2D
 cv Create Image
 cv Name Window


CV_bitdepth()
S=符号整型
U=无符号整型
F=浮点型
CV_8(位数)U(类型)G(矩阵)1(通道) 一个8位无符号整形单通道矩阵
CV_32FG2 32位浮点型双通道矩阵


图像数据类型:
IPL_DEPTH_<bit_depth>(S|U|F)
IPL_DEPTH_8U 8位无符号整型


头文件:
<cv.h>
<cvaux.h>
<highgui.h>
<ml.h>
<cxcore.h>


基础结构:


其中,CvPoint为二维坐标点整型,2D32F为2维浮点型,以此类推。

CyScalar是一个颜色结构体类,有四个数组元素,分别代表R,G,B,第四个元素通常用来表示透明色.

typedef struct CvScalar
 {
  double val[4]
 }
 CvScalar;


扩展——


其中Cvpoint

inline CvPoint cvPoint( int x, int y );
inline CvPoint cvPointFrom32f( CvPoint2D32f point )

分别作用为:返回一个cvPoint值,

将一个2D32f值转换为cvPoint值并返回。


函数原型:

void cvLine( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color, int thickness=1, int line_type=8, int shift=0 );

功能:绘制连接两个点的线段
  • img 图像。
  • pt1 线段的第一个端点。
  • pt2 线段的第二个端点。
  • color 线段的颜色。
  • thickness 线段的粗细程度。
  • line_type 线段的类型。
    8 (or 0) - 8-connected line(8邻接)连接 线。
    4 - 4-connected line(4邻接)连接线。
    CV_AA - antialiased 线条。
shift 坐标点的小数点位数。
函数cvLine 在图像中的点1和点2之间画一条线段。线段被图像或感兴趣的矩形(ROI rectangle)所裁剪。对于具有整数坐标的non-antialiasing 线条,使用8-连接或者4-连接Bresenham 算法。画粗线条时结尾是圆形的。画 antialiased 线条使用高斯滤波。要指定线段颜色,用户可以使用使用宏CV_RGB( r, g, b )。
而且指定线条颜色的时候用到的宏CV_RGB(r,g,b)定义为#define CV_RGB( r, g, b ) cvScalar( (b), (g), (r), 0 ),由此可见,实际上起作用的颜色是看cvScalar中的b,g,r顺序,线段颜色就不言而喻了
利用CvScalar,CvLine画线:
// qwsds.cpp : Defines the entry point for the console application.
//


#include "stdafx.h"

#include "highgui.h"

#include "stdio.h"

int main()
{
	CvPoint pt1;
	pt1=cvPoint(100,200);
	printf("x:%d,y:%d\n",pt1.x,pt1.y);

	CvPoint pt2;
	pt2=cvPoint(200,320);
	printf("x:%d,y:%d\n",pt2.x,pt2.y);

	CvScalar color;
	color=cvScalar(100,0,200);//蓝 绿 红。RGB
	printf("v1:%f v2:%f v3:%f\n",color.val[0],color.val[1],color.val[2]);

	IplImage *img=0;
	img=cvLoadImage("D:\\Blue hills.jpg");

	cvLine(img,pt1,pt2,color,2);

	cvNamedWindow("draw");

	cvShowImage("draw",img);

	cvWaitKey();

	return 0;
}
</pre><pre code_snippet_id="421021" snippet_file_name="blog_20140707_14_8402014" name="code" class="cpp"><strong><span style="color:#ff0000;">CvLine</span></strong>
void cvLine( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color,
             int thickness=1, int line_type=8, int shift=0 );
img
图像。
pt1
线段的第一个端点。
pt2
线段的第二个端点。
color
线段的颜色。
thickness
线段的粗细程度。
line_type
线段的类型。
8 (or 0) - 8-connected line(8邻接)连接 线。
4 - 4-connected line(4邻接)连接线。
CV_AA - antialiased 线条。
shift
坐标点的小数点位数。

函数cvLine 在图像中的点1和点2之间画一条线段。线段被图像或感兴趣的矩形(ROI rectangle)所裁剪。对于具有整数坐标的non-antialiasing 线条,使用8-连接或者4-连接Bresenham 算法。画粗线条时结尾是圆形的。画 antialiased 线条使用高斯滤波。要指定线段颜色,用户可以使用使用宏CV_RGB( r, g, b )。



CvSize sz;
设置一个矩形。
	CvSize sz;
	sz=cvSize(640,480);
	printf("width:%d,height:%d\n",sz.width,sz.height);

将这个矩形作为Image显示出来:
	IplImage *p;
	p=cvCreateImage(sz,IPL_DEPTH_8U,3);//sz矩形的宽,高(将结构体传进去),深度,颜色通道数)
	cvNamedWindow("Image");
	cvShowImage("Image",p);
	cvWaitKey(0);

其中cvCreateImage创建了一个矩形!

CvRect矩阵框的偏移量
typedef struct CvRect
 {
  int x; /* 方形的最左角的x-坐标  */
  int y; /* 方形的最上或者最下角的y-坐标 */
  int width; /* 宽 */
  int height; /* 高 */
 }
 CvRect;

应用:(利用了CvRectangle)
CvRectangle:
void cvRectangle( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color,
                  int thickness=1, int line_type=8, int shift=0 );

img
图像.
pt1
矩形的一个顶点。
pt2
矩形对角线上的另一个顶点
color
线条颜色 (RGB) 或亮度(灰度图像 )(grayscale image)。
thickness
组成矩形的线条的粗细程度。取负值时(如 CV_FILLED)函数绘制填充了色彩的矩形。
line_type
线条的类型。见cvLine的描述
shift
坐标点的小数点位数。
 

函数 cvRectangle 通过对角线上的两个顶点绘制矩形。


#include "highgui.h"

#include "stdio.h"

int main(int argc, char* argv[])
{
	CvSize sz;//CvSize 数据类型 C大写,定义。
	sz=cvSize(640,480);//给sz赋值。
	printf("width:%d,height:%d\n",sz.width,sz.height);
	IplImage *img=0;
	img=cvCreateImage(sz,IPL_DEPTH_8U,3);//创建而不是载入。
	CvRect rect;
	rect=cvRect(50,30,100,150);//左上坐标,长度,宽度。
	CvPoint pt1=cvPoint(rect.x,rect.y);
	CvPoint pt2=cvPoint(rect.x+rect.width,rect.y+rect.height);
	cvRectangle(img,pt1,pt2,cvScalar(0,0,255),2);
	cvNamedWindow("create");
	cvShowImage("create",img);
	cvWaitKey();
	return 0;
}

只有在创建了一个矩形(或者指针已经指向了一张图才可以用cvRectangle函数在图里画矩形(画线也一样))。
其中cvRectangle利用apt1,apt2两个点,和颜色方案cvScalar,以及粗细程度2,将绘制的矩形传递给指针p2,然后在建立的图案区域AAA内显示矩形。
复制图像:
IplImage *mp1=cvCloneImage(img);//把图像img复制给mp1.
</pre></div><div class="para" style="margin:15px 0px 5px; text-indent:2em; line-height:24px; font-family:arial,宋体,sans-serif; font-size:14px"><pre code_snippet_id="421021" snippet_file_name="blog_20140707_20_810661" name="code" class="cpp" style="color: rgb(51, 51, 51);">	cvNamedWindow("create");
	cvShowImage("create",img);//img需要事先指向图像
	IplImage *p2=cvCloneImage(img);
	cvNamedWindow("clone");
	cvShowImage("clone",p2);
	cvWaitKey();

      保存图像到文件

int cvSaveImage( const char* filename, const CvArr* image );

filename 
文件名,如果对应的文件已经存在,则将被复盖。
image 
要保存的图像。

函数cvSaveImage保存图像到指定文件。图像格式的的选择依赖于filename的扩展名,请参考cvLoadImage。只有8位单通道或者3通道(通道顺序为'BGR' )可以使用这个函数保存。如果格式,深度或者通道不符合要求,请先用cvCvtScale 和cvCvtColor转换;或者使用通用的cvSave保存图像为XML或者YAML格式。

#include <highgui.h>

int main()

{
     IplImage * test=NULL;
     test = cvLoadImage ("D:\\demo.jpg");
     cvNamedWindow("test_demo",1);
	 cvMoveWindow("test_demo",800,10);
     cvShowImage("test_demo",test);
	 cvSaveImage("D:\\123.jpg",test);
     cvWaitKey(0);
     cvDestroyWindow("test_demo");
     cvReleaseImage(&test);
     return 0;
}

其中cvSaveImage在指定目录建立一个新文件(图像)。
总结:

OpenCV里有两个单词,Image,Window,它们各自代表的是载入的图像(用IplImage指针表示),放置图像的窗口。


1.在存在Window的前提下,即cvNamedWindow("窗口名",是否根据Image进行调整的指标.),
2.让IplImage指针指向Image,即cvLoadImage("Image",指针名).除去载入的方法外,也可以创建:
(1).定义一个CvSize类型的矩形sz.
(2).赋予其宽,高.sz=CvSize(640,480)
(3).p=cvCreateImage(sz,IPL_DEPTH_8U,3).第二个参数为深度,例为8位无符号整型,3通道.
3.再将Image导入Window,才能让Image显示出来,即cvShowImage(Window,image的指针).
另外,除了必要的知识外,大部分函数在使用的时候可以直接在博客开头的Page手册里查阅使用方案,系统全面的文档提供了很高的支持。感觉和Linux查阅技术文档来进行操作有些相同之处。

因为和C文件IO输入输出差不多 顺便复习一下:
1.FILE *fopen(char *filename, *type)


如果要打开一个CCDOS子目录中, 文件名为CLIB的二进制文件, 可写成:


         fopen("c:\\ccdos\\clib", "rb");         


如果成功的打开一个文件, fopen()函数返回文件指针,否则返回空指针(NULL)。由此可判断文件打开是否成功。


表    文件操作类型
 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
字符                  含义      
 ──────────────────────────── 
"r"             打开文字文件只读             
"w"             创建文字文件只写               
"a"             增补, 如果文件不存在则创建一个              
"r+"            打开一个文字文件读/写              
"w+"            创建一个文字文件读/写              
"a+"            打开或创建一个文件增补               
"b"             二进制文件(可以和上面每一项合用)              
"t"             文这文件(默认项)         
━━━━━━━━━━━━━━━━━━━━━━━━━━━━


fopen()函数中第一个形式参数表示文件名, 可以包含路径和文件名两部分。 如:          "B:TEST.DAT"
"C:\\TC\\TEST.DAT"
如果将路径写成"C:\TC\TEST.DAT"是不正确的, 这一点要特别注意。




2. fclose()函数
fclose()函数用来关闭一个由fopen()函数打开的文件 , 其调用格式为:
          int fclose(FILE *stream);  


#iclude<stdio.h>
main()
{
	FILE *fp;                  /*定义一个文件指针*/
	int i;
	fp=fopen("CLIB", "rb");    /*打开当前目录名为CLIB的文件只读*/ 
	if(fp==NULL)               /*判断文件是否打开成功*/
		puts("File open error");/*提示打开不成功*/
	i=fclose(fp);              /*关闭打开的文件*/
	if(i==0)                   /*判断文件是否关闭成功*/
		printf("O.K");           /*提示关闭成功*/
	else                
		puts("File close error");/*提示关闭不成功*/
} 




3.文件的顺序写函数
     fprintf()、fputs()和fputc()函数均为文件的顺序写操作函数,其调用格式如下:
 int fprintf(FILE *stream, char *format, <variable-list>);
        int fputs(char *string, FILE *steam);        
int fputc(intch, FILE *steam);


fprintf() 函数的返回值为实际写入文件中的字符个数(字节数)。如果写错误, 则返回一个负数; fputs()函数返回0时表明将string指针所指的字符串写入文件中的操作成功, 返回非0时,表明写操作失败。  fputc()函数返回一个向文件所写字符的值, 此时写操作成功,否则返回EOF(文件结束结束其值为-1, 在stdio.h中定义)表示写操作错误。   fprintf( ) 函数中格式化的规定与printf( ) 函数相同,所不同的只是fprintf()函数是向文件中写入。而printf()是向屏幕输出。


4.文件的顺序读操作函数
        fscanf()、fgets()和fgetc()函数
函数fscanf()、fgets()和fgetc()均为文件的顺序读操作函数, 其调用格式 如下:
int fscanf(FILE *stream, char *format, <address-list>); 
        char fgets(char *string, int n, FILE *steam); 
        int fgetc(FILE *steam);


fscanf()函数的用法与scanf()函数相似,只是它是从文件中读到信息。 fscanf()函数的返回值为EOF(即-1), 表明读错误, 否则读数据成功。  fgets()函数从文件中读取至多n-1个字符(n用来指定字符数), 并把它们放入string指向的字符串中, 在读入之后自动向字符串未尾加一个空字符, 读成功返回string指针,  失败返回一个空指针。  fgetc()函数返回文件当前位置的一个字符,读错误时返回EOF。 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值