Cpp--opencv中连续储存多帧图片技巧

做过opencv方面的人都知道,在项目中经常需要自动要输出几帧图片,但是好像每次都要手动去改储存图片的名字,如果不这样,虽然程序执行了,但是因为名字相同,还是会覆盖前面的几帧。

cvSaveImage函数中的图片名字是个字符串,不可能在程序中每次自动更改,那我们用什么方法呢?我们需要在这个字符串上做手脚。大家知道,C++中并没有字符串类型,我们用的,都可以认为是字符数组。那么这个地址值其实也就是一个指向特殊字符串地址的指针。

于是,用分解的方法就可以实现这个目的。例如地址为“E:/test/i.jpg”。我们不可以直接改变i的值,那么我们就可以分为:“E:/test/“,i,”.jpg“三个字符串。可能就有人要问了:i不是for循环中定义的整形数么?(for(int i=0;i<10;i++))。对,确实是这样,但是在头文件<stdlib.h>下,我们有一些可以进行数据类型转换的函数。我们这里用到了itoa函数。

先看看定义:char   *itoa(int   value,char   *string,int   radix) 将整数value转换成字串存入string,radix为转换所用基数.。最终我们得到的还是一个指向字符串的指针,那么就ok了。

接下来我们直接看看代码和实现:

#include "camera.h"
#include <highgui.h>
#include <stdio.h>
#include<iostream>
#include "string.h"
#include<stdlib.h>

using namespace std;
using namespace cv;

int main()
{
	int cam_count;
	//仅仅获取摄像头数目
	cam_count = CCamera::CameraCount();
	printf("There are %d cameras.\n", cam_count);


	//获取所有摄像头的名称
	for(int i=1; i <= cam_count; i++)
	{
		char camera_name[1024];  
		CCamera::CameraName(i, camera_name, sizeof(camera_name) );
		printf("Camera #%d's Name is '%s'.\n", i, camera_name);
	}
	
	if(cam_count==0)
		return -1;

	CCamera camera1;
	CCamera camera2;
	//打开第一个摄像头,检查第二个摄像头
	if(! camera1.OpenCamera(1, 10000,10000)) //用代码制定图像宽和高
	{
		fprintf(stderr, "Can not open camera1.\n");
		return -1;
	}
	cvNamedWindow("camera1");
	//Sleep(100);
	if (cam_count>1)
	{
		if(! camera2.OpenCamera(1)) 
			//	if(! camera2.OpenCamera(1, 2048,1536)) //用代码制定图像宽和高
		{
			fprintf(stderr, "Can not open camera2.\n");
			return -1;
		}
		cvNamedWindow("camera2");
	}

	IplImage *pFrame1 = 0;
	IplImage *pFrame2 = 0;
	if (cam_count==1)//连续采集
	{
		while(1)
		{
			//获取帧
			for(int i=0;i<10;i++){
			pFrame1 = camera1.QueryFrame();
			//显示
			//char *arr1 = new char[];
		   char arr1[] = "E:/test/";
		   char *arr2 = new char[];
		   itoa(i,arr2,10);
	       char arr3[] = ".jpg";
		   strcat(arr1,arr2);
		   strcat(arr1,arr3);
		   cout<<arr1<<endl;
		   cout<<"true"<<endl;
		    //cvShowImage("camera1", pFrame1);
			cvSaveImage(arr1, pFrame1 );  
		 	}
			   break;
			if (cvWaitKey(20) == 'q')//不懂,这是检测什么?
			   break;
		}
		
	}
	else
	{
		while(1)
		{
			//获取一帧
			pFrame1 = camera1.QueryFrame();
			
			//显示
			cvShowImage("camera1", pFrame1);
			pFrame2 = camera2.QueryFrame();
			cout<<"false"<<endl;
			//显示
			cvShowImage("camera2", pFrame2);
			if (cvWaitKey(20) == 'q')
				break;
		}
	}
	camera1.CloseCamera(); //可不调用此函数,CCamera析构时会自动关闭摄像头
	cvDestroyWindow("camera1");
	if (cam_count>1)
	{
		camera2.CloseCamera(); //可不调用此函数,CCamera析构时会自动关闭摄像头
		cvDestroyWindow("camera2");
	}
	
	return 0;
}
if (cam_count==1)//连续采集
	{
		while(1)
		{
			//获取帧
			for(int i=0;i<10;i++){
			pFrame1 = camera1.QueryFrame();
			//显示
			//char *arr1 = new char[];
		   char arr1[] = "E:/test/";
		   char *arr2 = new char[];
		   itoa(i,arr2,10);
	       char arr3[] = ".jpg";
		   strcat(arr1,arr2);
		   strcat(arr1,arr3);
		   cout<<arr1<<endl;
		   cout<<"true"<<endl;
		    //cvShowImage("camera1", pFrame1);
			cvSaveImage(arr1, pFrame1 );  
		 	}
			   break;
			if (cvWaitKey(20) == 'q')//不懂,这是检测什么?
			   break;
		}
		
	}
注意在cvSaveImage中arr1本身就是个字符串数组,不需要再加引号。这样,就完美的实现了用不同的名称储存多帧图像。



但是还是存在一些问题就是arr1的内存会崩溃,不知道是不是因为在后面多次使用字符串连接函数。待解决。




我们再附上常用的数据类型转换函数:

char   *ultoa(unsigned   long   value,char   *string,int   radix)   
将无符号整型数value转换成字符串并返回该字符串,radix为转换时所用基数   
char   *ltoa(long   value,char   *string,int   radix)   
将长整型数value转换成字符串并返回该字符串,radix为转换时所用基数   
char   *itoa(int   value,char   *string,int   radix) 
将整数value转换成字串存入string,radix为转换所用基数.   
double atof(char   *nptr)                   
将字符串nptr转换成双精度数,并返回这个数,错误返回0   
int     atoi(char   *nptr)                               
将字符串nptr转换成整型数,     并返回这个数,错误返回0   
long     atol(char   *nptr)     
将字符串nptr转换成长整型数,并返回这个数,错误返回0   
double strtod(char   *str,char   **endptr)   
将字符串str转换成双精度数,并返回这个数,   
long strtol(char   *str,char   **endptr,int   base)   
将字符串str转换成长整型数,   并返回这个数,


我们来看另一种形式的实现:

#include<iostream>
#include<sstream>
#include<string>
using namespace std;
double sciToDub(const string&str){
	stringstream ss(str);
	double d=0;
	ss>>d;
	if(ss.fail()){
		string s="unable to format";
		s+=str;
		s+="as a number!";
		throw(s);
	}
	return (d);
}
int main(){
	try{
		cout<<sciToDub("1.234e5")<<endl;
		cout<<sciToDub("6.02e-2")<<endl;
		cout<<sciToDub("asdf")<<endl;
	}
	catch(string &e){
		cerr<<"whoops:"<<e<<endl;
	}
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值