探索:怎樣去顯示fps

来源:互联网 发布:新房装修必知 编辑:程序博客网 时间:2024/04/28 18:30

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

先說速度的問題吧。說道速度,那就要拿東西來計時,計算每一幀需要消耗的時間,取個倒數,就是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*1024long 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);}//接收indexif(-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
原创粉丝点击