樹莓派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