1. 程式人生 > >樹莓派3B在QT環境下使用opencv呼叫自帶攝像頭使用拍照,記憶體中bmp與jpg互轉

樹莓派3B在QT環境下使用opencv呼叫自帶攝像頭使用拍照,記憶體中bmp與jpg互轉

樓主最近在做一個人臉識別的專案,剛好有個一個樹莓派3B,於是準備拿來做終端使用,使用命令列和python拍照都很簡單,但是速度感人,就想使用opencv拍照,結果網上很多方法都有問題,只能使用USB的攝像頭,最終用了gayhub上的一個開源專案raspicam成功呼叫了opencv

地址:https://github.com/cedricve/raspicam


raspicam提供了2種方式拍照,有一種是直接使用C++的,還有一種使用opencv的,opencv安裝方法網上很多,和linux一樣需要自己編譯,等上2小時左右就行了,然後去raspicam的地址下載原始碼解壓,cd進入資料夾,然後:

mkdir build
cd build
cmake ..

等一會兒就完成了

接下來測試一下,我用的開發環境是QT(推薦使用apt-fast下載,不然等半天,安裝教程:http://blog.csdn.net/coekjin/article/details/52049273),新建一個專案,開啟pro檔案加入以下內容:

INCLUDEPATH += /usr/local/include \
                /usr/local/include/opencv \
                /usr/local/include/opencv2 \
                /usr/local/include/raspicam

LIBS += /usr/local/lib/libopencv_highgui.so \
        /usr/local/lib/libopencv_core.so    \
        /usr/local/lib/libopencv_imgproc.so \
        /usr/local/lib/libopencv_video.so \
        /usr/local/lib/libopencv_videoio.so \
        /usr/local/lib/libopencv_videostab.so \
        /usr/local/lib/libraspicam.so \
        /usr/local/lib/libraspicam_cv.so \
        -L/usr/local/lib \
        -lopencv_core \
        -lopencv_imgcodecs \
        -lopencv_highgui \
        -lopencv_video \
        -lopencv_videoio \
        -lopencv_videostab \
        -lraspicam \
        -lraspicam_cv

然後複製gayhub上的第一段程式碼,修改成子函式呼叫:

#include <ctime>
#include <fstream>
#include <iostream>
#include <raspicam/raspicam.h>
using namespace std;
 
int shoot() {
	raspicam::RaspiCam Camera; //Camera object
	//Open camera 
	cout<<"Opening Camera..."<<endl;
	if ( !Camera.open()) {cerr<<"Error opening camera"<<endl;return -1;}
	//wait a while until camera stabilizes
	cout<<"Sleeping for 3 secs"<<endl;
	sleep(3);
	//capture
	Camera.grab();
	//allocate memory
	unsigned char *data=new unsigned char[  Camera.getImageTypeSize ( raspicam::RASPICAM_FORMAT_RGB )];
	//extract the image in rgb format
	Camera.retrieve ( data,raspicam::RASPICAM_FORMAT_RGB );//執行完這句data就是bmp24的原始資料,可以給它加上檔案頭儲存為bmp
	//save
	std::ofstream outFile ( "raspicam_image.ppm",std::ios::binary );
	outFile<<"P6\n"<<Camera.getWidth() <<" "<<Camera.getHeight() <<" 255\n";
	outFile.write ( ( char* ) data, Camera.getImageTypeSize ( raspicam::RASPICAM_FORMAT_RGB ) );
	outFile.close()//建議加上
	cout<<"Image saved at raspicam_image.ppm"<<endl;
	//free resrources    
	delete[] data;//原始碼是delete data,建議修改成和我一樣的
	return 0;
}

修改程式碼中的檔案位置,編譯執行,就可以看到儲存結果,ppm格式的,打不開的話可以拖到你的播放器裡面試試

如果要轉成BMP格式,給它加上58位的檔案頭就行了,程式碼在:http://blog.csdn.net/libin88211/article/details/36186535

當然如果只是這樣是不需要opencv的,而且bmp格式的檔案太大,所以可以直接使用gayhub下面的程式碼直接儲存bmp或者jpg,程式碼裡面改下檔名就行了:

#include <ctime>
#include <iostream>
#include <raspicam/raspicam_cv.h>
using namespace std; 
 
int shootopencv () {
   
	time_t timer_begin,timer_end;
	raspicam::RaspiCam_Cv Camera;
	cv::Mat image;
	int nCount=100;
	//set camera params
	Camera.set( CV_CAP_PROP_FORMAT, CV_8UC1 );
	//Open camera
	cout<<"Opening Camera..."<<endl;
	if (!Camera.open()) {cerr<<"Error opening the camera"<<endl;return -1;}
	//Start capture
	cout<<"Capturing "<<nCount<<" frames ...."<<endl;
	time ( &timer_begin );
	for ( int i=0; i<nCount; i++ ) {
		Camera.grab();
		Camera.retrieve ( image);
		if ( i%5==0 )  cout<<"\r captured "<<i<<" images"<<std::flush;
	}
	cout<<"Stop camera..."<<endl;
	Camera.release();
	//show time statistics
	time ( &timer_end ); /* get current time; same as: timer = time(NULL)  */
	double secondsElapsed = difftime ( timer_end,timer_begin );
	cout<< secondsElapsed<<" seconds for "<< nCount<<"  frames : FPS = "<<  ( float ) ( ( float ) ( nCount ) /secondsElapsed ) <<endl;
	//save image 
	cv::imwrite("raspicam_cv_image.jpg",image);
	cout<<"Image saved at raspicam_cv_image.jpg"<<endl;
}

但是這也不是樓主想要的,因為是儲存到磁碟上的jpg,我的臘雞SD卡速度肯定很慢,下面是直接在記憶體中轉化成jpg的方法:

int w=Camera.getWidth(),h=Camera.getHeight();
    IplImage *pIpl = cvCreateImage(cvSize(w, h), 8, 3);
    //memcpy(pIpl->imageData, data, w * h * 3 * sizeof(char));
    pIpl->imageData=(char*)data;//這裡的data就是之前的bmp原始資料
    cv::Mat tempMat=cv::cvarrToMat(pIpl);
    std::vector<uchar> buf;
    cv::imencode(".jpg",tempMat,buf);//也可以改為其他格式
    dump((char*)&buf[0],buf.size(),"/root/Pictures/t.jpg");
    delete[] data;
    data=nullptr;
    cvReleaseImage(&pIpl);//別忘記釋放data和pIpl!!!

其中dump的程式碼是:

void dump(char *p, size_t len, const char *filename)
{
    FILE *fp =  fopen(filename, "w+b");
    //fopen_s(&fp, filename, "w+b");
    fwrite(p,sizeof(char),len,fp);
    fclose(fp);
}

這樣就完成了記憶體中圖片的轉化,樓主拍的照片是720*480解析度的,轉化為jpg基本都在50毫秒內,在樹莓派上算是勉強能接受吧,具體其它用法在標頭檔案裡面很詳細,各種引數都可以自己設定


轉載請註明出處:http://blog.csdn.net/rtduq/article/details/79509720