利用文件读写,完成载入图片功能(可以局部的载入)

本程序源于一个想法,如何将图片直接上传到FTP。能想到的一个可行的方法就是在Ftp站点下新建一个文件,打开文件并传输数据。吸取了OpenCV教程一书例4-4与例4-5及相关知识。本项目由以下两个有机组成部分构成:1、将图像的颜色数据存入文件2、从文件读取要求区域的图像的颜色数据

本项目由以下两个有机组成部分构成:
1、将图像的颜色数据存入文件
2、从文件读取要求区域的图像的颜色数据

 

#include  " cxcore.h "
#include 
" highgui.h "
#include 
" stdlib.h "

int  main(  int  argc,  char **  argv )
{
   
   IplImage
* img = 0;
   img   
= cvLoadImage("20080514150135664.jpg",CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);
   CvFileStorage
* fs = cvOpenFileStorage("example.yml",0 , CV_STORAGE_WRITE);
   cvWrite(fs , 
"Image" ,img , cvAttrList(0,0));
   system(
"PAUSE");
   cvReleaseFileStorage(
&fs);
   cvReleaseImage(
&img);
   
return 0;
}

 

#include  < stdio.h >
#include 
< highgui.h >
#include 
" cxcore.h "

int  main(  int  argc,  char **  argv )
{

   CvSeq
* seq;
   CvSeqReader reader;
   CvPoint point 
= cvPoint(100,100);
   CvSize size 
= cvSize(400,350);
   IplImage
* img = cvCreateImage(size,IPL_DEPTH_8U,3);
   uchar 
*picData ;
   
int step;
   
int channels;
   
   picData 
= (uchar*)img->imageData;
   channels 
= img->nChannels;
   step 
= img->widthStep/sizeof(uchar);
   
    CvFileStorage
* fs = cvOpenFileStorage( "example.yml"0, CV_STORAGE_READ );
   CvFileNode
* parent = cvGetFileNodeByName( fs, 0"Image" );

   CvFileNode
* data = cvGetFileNodeByName( fs, parent, "data" );
   CvFileNode
* imgWidth = cvGetFileNodeByName( fs, parent, "width" );
   CvFileNode
* imgHeight = cvGetFileNodeByName( fs, parent, "height" );
    
int width,height;
   width 
= imgWidth->data.i;
   height 
= imgHeight->data.i;
   seq 
= data->data.seq;
   
    cvStartReadSeq( seq, 
&reader, 0 );
   
   
int total = seq->total;
   
int value;
   
int i,j,k;
   
for(i=0;i<size.height + point.y;i++)
   
{
      
for(j=0;j<width;j++)
      
{
         
for(k = 0;k<channels;k++)
         
{
            CvFileNode
* pt = (CvFileNode*)reader.ptr;
            
if(j<size.width+point.x&&j>=point.x&&i>=point.y)
            
{
               value 
= pt->data.i;
               picData[(i
-point.y)*step+(j-point.x)*channels+k]  = value;
            }

            CV_NEXT_SEQ_ELEM(seq
->elem_size, reader );
         }

         
      }

   }

   cvNamedWindow(
"region of image",CV_WINDOW_AUTOSIZE);
   cvShowImage(
"region of image",img);
   cvWaitKey(
0);
   cvReleaseImage(
&img);
   cvDestroyWindow(
"region of image");
   
return 0;
}

 

 example.yml的大体格式如下

 

%YAML:1.0
image: !!opencv-image
   width: 640
   height: 480
   origin: top-left
   layout: interleaved
   dt: "3u"
   data: [ 128, 160, 143, 131, 160, 144, 134, 158, 146, 135, 157, 145,
    ...
    ]

 

虽然程序段很简短,但我也是苦做了一天完成的成果。其间绕了不少弯路,不过也对很多知识点加深了了解。如下:
1、访问图像元素时的坐标(i,j)分别指的是纵坐标和横坐标。与通常的坐标表示习惯不一样。据我的理解,这样做是因为图像数据的读写以origin结构的起始点一行一行来的,所以IplImage的结构才只有widthStep,而没有heighthStep。
2、还有一个有趣的地方就是CV_NEXT_SEQ_ELEM宏的使用
/* move reader position forward */
#define CV_NEXT_SEQ_ELEM( elem_size, reader ) /
{ /
if( ((reader).ptr += (elem_size)) >= (reader).block_max ) /
{ /
cvChangeSeqBlock( &(reader), 1 ); /
} /
}

很显然根据该宏的定义,没有办法随心所欲的移动,受reader结构的block_max所限,一次没有办法移动太大的尺寸。

项目生成的yaml文件大小有4M多,原图像文件90Kb,所以没有实际意义,但是我觉得理论上的意义还是挺大的,这是个雏形,展现了如下诸多可能:
1、可以通过Ftp直接传递应用程序的数据
2、可以将图像存入自定义格式的文件中,并从该自定义文件读取图像(可以局部的载入)
3、其实是由二衍生的具体可能性就是可以局部载入很大的图片,仅仅显示你需要的部分(当然前提是你知道你需要哪部分),大大提高效率(比如地图图像文件,超过10M都是很正常的,很明显如果一次全部载入将会占用很多系统资源)

 

以下是网友回复的意见,摘录于下:

其实你要用ftp传输图像可以分为2步:

1. 将图像作为普通文件下载到本地
2. 读取下载的文件

如果是图像太大,需要读局部区域的图像,可以用GDAL来做。GDAL是专门用来处理
遥感图像的,对于多波段、超大影像都有很好的支持。我过段时间打算将Gdal和OpenCV
结合到一起,抽象一个CvxGdalWrap类,用GDAL完成区域IplImage格式的读写。

最后是本文文件太大的问题。如果图像比较小问题还不太严重。但是如果图像很大的话,
用文本格式可能会生成几十MB甚至几百MB大小的文件。文件太大对于读写的速度会有很大的影响,
对于网络传输的影响更大。

但是如果只是将文本转换为二进制,依然会存在很大的冗余。当然,压缩图像的话会用到很多算法。
因此,最好的方式是用现成的图像库,直接把图像保存为png或jpg等压缩格式。

                                                      -----------chai2010

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值