探索:怎樣去顯示fps

前兩天把攝像頭網絡傳輸程序搞定了,傳輸效果也挺不錯,至少沒有出現畫面錯誤。那接下來,我想探究一下這個程序的效率:傳輸速度,顯示速度,內存佔用等等。

先說速度的問題吧。說道速度,那就要拿東西來計時,計算每一幀需要消耗的時間,取個倒數,就是fps了。怎麼計時呢?

把c語言 計時作爲關鍵字百度一下,有好幾個方法。那是不是隨便選一個用呢,答案肯定非也。如果都一樣,那還需要那麼多方法幹什麼,是吧~所以得選一個適合的,適合當前這個問題的。那我先把各種方法來實驗一遍,找到一個最好的用:

首先是clock():

這個函數在<time.h>中,返回值類型是clock_t,精度:毫秒級,誤差比較大

#include <stdio.h>
#include <time.h>
int main() {
	clock_t start, end;
	long timeuse;
	start = clock();
	printf("start : %d\n", start);
	sleep(1);
//	usleep(200000);
	end = clock();
	printf("end : %d\n", end);
	timeuse = end - start;
	printf("time use : %d\n", timeuse);
	return 0;
}

運行了10次,居然沒有一次是精準的,誤差很大。。。這讓我很驚訝,網上的代碼運行起來能精確的毫秒級,但我不清楚爲什麼,誤差這麼大。。。顯然這個肯定不能用在我的程序裏。

然後gettimeofday():

在<sys/time.h>中,無返回值,精度:微妙級,很精準!!

#include <stdio.h>
#include <sys/time.h>
int main() {
	struct timeval t_start, t_end;
	long timeuse;
	gettimeofday(&t_start, NULL);
	sleep(2);
	usleep(500000);
	gettimeofday(&t_end, NULL);
	timeuse = 1000000 * (t_end.tv_sec - t_start.tv_sec) + t_end.tv_usec - t_start.tv_usec;
	timeuse /= 1000;
	printf("time used : %d ms\n", timeuse);
	return 0;
}
timeval 结构定义为:
struct timeval{
    long tv_sec;     //秒
    long tv_usec;  //微秒
};

經過測試,這個函數準精度很高,精度也很高!就選這個了~~

還有一個time():

頭文件是<time.h>,返回值是以格林尼治时间(GMT)为标准,从1970年1月1日00:00:00到现在的此时此刻所经过的秒数,精度嘛,就是秒啦

#include <stdio.h>
#include <time.h>
int main() {
	time_t start,end;
	start =time(NULL);//or time(&start);
	printf("start : %d\n", start);	
	//…calculating…
	sleep(1);

	end =time(NULL);
	printf("end : %d\n", end);
	printf("time used = %d\n", end - start);
	return 0;	
}
明顯這個也不符合我的需求。。。

但是這些方法都能獲取時間和經過的時間,適用於不同的場合吧~

接下來把第二種方法加到我的服務端程序中:

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <string.h>

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

#define BUFFSIZE 16*1024

long Time_calc(struct timeval start, struct timeval end) {
	return (1000000 * (end.tv_sec - start.tv_sec) + end.tv_usec - start.tv_usec) / 1000;
}

int main(int argc, char *argv[]) {
	int skfd, cnfd, addr_len, i;
	long imagedataleft = 0;
	struct sockaddr_in srv_addr, clt_addr;
	int portnumber;
	char hello[] = "~~WELCOME~~\n";
	char *databuff = {0};
	int framerate = 0;
	char sync[2] = {0, 0};

	struct timeval t_start, t_end;
	long timeuse;

	IplImage *frame = 0, header;
	
	if(2 != argc || 0 > (portnumber = atoi(argv[1]))) {
		printf("Usage:%s port\n", argv[0]);
		exit(1);
	}
	if(-1 == (skfd = socket(AF_INET, SOCK_STREAM, 0))) {
		perror("Socket Error:");
		exit(1);
	}
	bzero(&srv_addr, sizeof(struct sockaddr_in));
	srv_addr.sin_family = AF_INET;
	srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	srv_addr.sin_port = htons(portnumber);
	if(-1 == bind(skfd, (struct sockaddr *)(&srv_addr), sizeof(struct sockaddr))) {
		perror("Bind error:");
		exit(1);
	}
	//開啓監聽
	if(-1 == listen(skfd, 4)) {
		perror("Listen error:");
		exit(1);
	}

	//阻塞接受請求	
	addr_len = sizeof(struct sockaddr_in);
	if(-1 == (cnfd = accept(skfd, (struct sockaddr *)(&clt_addr), &addr_len))) {
		perror("Accept error:");
		exit(1);
	}
	printf("Connect from %s:%u ...!\n", inet_ntoa(clt_addr.sin_addr), ntohs(clt_addr.sin_port));
	//初次應答	
	if(-1 == write(cnfd, hello, strlen(hello))) {
		perror("Send error:");
		exit(1);
	}

	//接收index	
	if(-1 == read(cnfd, (char*)&header, sizeof(IplImage))) {
		perror("Read index Error:");
		exit(1);
	}
	//用收到的index參數創建一個新的圖像
	frame = cvCreateImageHeader(cvSize(header.width, header.height), header.depth, header.nChannels); 

	//創建imageData接收緩存
	databuff = (char*)malloc(frame->imageSize);
	//圖像數據直接指向接收緩存
	frame->imageData = databuff;	
	//創建窗口
	cvNamedWindow("camera-server", 1);
	
	while(1) {
		gettimeofday(&t_start, NULL);
		imagedataleft = 0;
		while(imagedataleft < frame->imageSize) {
			if((i = read(cnfd, databuff + imagedataleft, BUFFSIZE)) == -1) {
				perror("Read Data Error:");
				exit(1);
			}
			//同步數據流
			if(-1 == write(cnfd, sync, 2)) {
				perror("Sync Error:");
				exit(1);
			}
			imagedataleft += BUFFSIZE;
			if(i < BUFFSIZE) {
				printf("recv finished!!\n");
				break;
			}
		}

		cvShowImage("camera-server", frame);
		if(-1 == write(cnfd, "frame done", 10)) {
			perror("Ack Error:");
			exit(1);
		}
		gettimeofday(&t_end, NULL);
		timeuse = Time_calc(t_start, t_end);
		printf("time used : %d || fps : %d\n", timeuse, 1000/timeuse);
		if(27 == cvWaitKey(1)) break;
	}
	
	free(databuff);
	cvReleaseImage(&frame); 
	cvDestroyWindow("camera-server");
	
	close(cnfd);
	close(skfd);
	exit(0);
}

再把cilent.c中的cvWaitKey()和cvShowImage()函數注釋掉,就是全速傳輸啦。

可是fps好像不太穩定,有時候是16~17幀,但喲時候只有一半了,待我仔細找找問題出在哪裏~

==================================

經過調試,終於發現了問題所在:

攝像頭會自動調節曝光時間:光線強時,曝光時間短,大概50ms;反之,時間會長,長達100ms以上(這是我筆記本自帶的攝像頭)。而數據傳輸處只消耗了3ms,一幀imageData有921600字節,可以忽略每次傳輸後的應答,那淨傳輸的速度就是307M/s,是很快的速度了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值