Realsystem
Установка и настройка библиотеки OpenCV в ОС Linux
Я проводил данную операцию в ОС Alt Linux с ядром 2.6.
Ссылка для подсказки: [1]
Для начала нужно установить необходимые пакеты Linux, такие как gcc, gcc4.1-c++, automake, autoconf. В Альт Линуксе они устанавливаются с помощью apt-get install. Затем нужно собрать и установить cmake и можно приступать к сборке OpenCV.
mkdir vision;cd vision
wget http://www.cmake.org/files/v2.8/cmake-2.8.2.tar.gz
tar -zxf cmake-2.8.2.tar.gz;cd cmake-2.8.2
./bootstrap; make; sudo make install
cd ../
wget http://downloads.sourceforge.net/project/opencvlibrary/opencv-unix/2.1/OpenCV-2.1.0.tar.bz2?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fopencvlibrary%2Ffiles%2Fopencv-unix%2F2.1%2F&ts=1281621769&mirror=citylan
tar -jxf OpenCV-2.1.0.tar.bz2;cd OpenCV-2.1.0
mkdir release;cd release
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D BUILD_PYTHON_SUPPORT=ON -D BUILD_EXAMPLES=ON ..; make; sudo make install
Еще нужно добавить собранные библиотеки в систему.
sudo echo "/usr/local/lib" > /etc/ld.conf.d/opencv.conf
sudo ldconfig
Теперь можно приступать к написанию программ с использованием OpenCV. Я взял библиотеку [2] и сделал распознавание маяка, который передается программе в виде простой картинки. Для отображения результатов в систему необходимо поставить пакет libgtk+2-devel
<source lang="cpp">
- pragma hdrstop
- include "CvQCodeBeacons.h"
- pragma package(smart_init)
- include <stdio.h>
- include <stdlib.h>
- include <stdio.h>
- include <math.h>
double angleF(char* datas, long int steps, CvSize szSrc, int bx,int by,int dx1,int dy1,int dx2,int dy2,int l, int b){
double inner=0, outer=0; double d1=sqrt(dx1*dx1+dy1*dy1); double d2=sqrt(dx2*dx2+dy2*dy2); double dx1n=dx1/d1, dy1n=dy1/d1; double dx2n=dx2/d2, dy2n=dy2/d2; for(int j=1; j<=b; j++){ for(int i=1; i<=l; i++){ long int adr,d_x,d_y; d_x=bx+j*(dx1n+dx2n)+i*dx1n; d_y=by+j*(dy1n+dy2n)+i*dy1n; if( d_x<0 || d_x>szSrc.width || d_y<0 || d_y>szSrc.height ){ inner+=0; }else{ adr=d_x*3+(szSrc.height-d_y)*steps+2; inner+=datas[adr]; }; d_x=bx+j*(dx1n+dx2n)+i*dx2n; d_y=by+j*(dy1n+dy2n)+i*dy2n; if( d_x<0 || d_x>szSrc.width || d_y<0 || d_y>szSrc.height ){ inner+=0; }else{ adr=d_x*3+(szSrc.height-d_y)*steps+2; inner+=datas[adr]; }; d_x=bx-j*(dx1n+dx2n)+i*dx1n; d_y=by-j*(dy1n+dy2n)+i*dy1n; if( d_x<0 || d_x>szSrc.width || d_y<0 || d_y>szSrc.height ){ outer+=0; }else{ adr=d_x*3+(szSrc.height-d_y)*steps+2; outer+=datas[adr]; }; d_x=bx-j*(dx1n+dx2n)+i*dx2n; d_y=by-j*(dy1n+dy2n)+i*dy2n; if( d_x<0 || d_x>szSrc.width || d_y<0 || d_y>szSrc.height ){ outer+=0; }else{ adr=d_x*3+(szSrc.height-d_y)*steps+2; outer+=datas[adr]; }; };}; return outer-inner;
};
double sqr(double a){
return a*a;
};
CvQCodeBeacon* mycvGetQCodeBeacons(IplImage *img, int ThresholdSteps, double k_front, double k_side){
CvQCodeBeacon* fbeacon = NULL; CvSize szSrc; szSrc.width=img->width; szSrc.height=img->height; CvSize szDiv2; szDiv2.width=szSrc.width/2; szDiv2.height=szSrc.height/2; IplImage* pyr = cvCreateImage(szDiv2, IPL_DEPTH_8U, 3); IplImage* tmp = cvCreateImage(szSrc, IPL_DEPTH_8U, 3);
cvPyrDown( img, pyr, 7 ); cvPyrUp( pyr, tmp, 7 ); IplImage* gray = cvCreateImage( szSrc, 8, 1 ); IplImage* tgray = cvCreateImage( szSrc, 8, 1 ); cvSetImageCOI( tmp, 2 ); cvCopy( tmp, tgray, 0 ); CvMemStorage* storage=cvCreateMemStorage(0); CvSeq* contours, result; for(int l=0; l<ThresholdSteps; l++){ if(l==0){ cvCanny( tgray, gray, 0, 100, 5 ); cvDilate( gray, gray, 0, 1 ); }else{ cvThreshold( tgray, gray, (l+1)*255/ThresholdSteps, 255, CV_THRESH_BINARY ); }; cvFindContours( gray, storage, &contours, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) ); while( contours ) { CvSeq* result = cvApproxPoly( contours, sizeof(CvContour), storage, CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0 ); int count = result->total;
if( count == 4 && fabs(cvContourArea(result,CV_WHOLE_SEQ)) > 100 && cvCheckContourConvexity(result) ){ int isPara=1; double x[5],y[5]; for(int i=0; i < count; i++){ CvPoint *pt=(CvPoint*)cvGetSeqElem( result, i ); x[i]=pt->x; y[i]=szSrc.height-pt->y; }; x[count]=x[0]; y[count]=y[0]; double l[5]; for(int i=1; i<=4; i++){ l[i]=sqrt(sqr(x[i-1]-x[i])+sqr(y[i-1]-y[i])); };
if( fabs(l[1]/(l[1]+l[3])-0.5)>0.1 ){ isPara=0; }; if( fabs(l[2]/(l[2]+l[4])-0.5)>0.1 ){ isPara=0; }; if( fabs(l[2]/(l[2]+l[3])-0.5)>0.2 ){ isPara=0; }; if( l[1]+l[2]>800 ){ isPara=0; };
double s_mul=(x[1]-x[0])*(x[2]-x[1])+(y[1]-y[0])*(y[2]-y[1]); double cos_a=s_mul/(l[1]*l[2]); if( cos_a > 0.3 ){ isPara=0; }; if( isPara ){ double cx=(x[0]+x[1]+x[2]+x[3])/4; double cy=(y[0]+y[1]+y[2]+y[3])/4; CvQCodeBeacon *bc=fbeacon; while( bc ){ double dist=sqrt(sqr(cx-bc->x)+sqr(cy-bc->y)); if( dist<5 ){ isPara=0; }; bc=bc->next; }; }; if( isPara ){ double idx1,idy1,idx2,idy2,idx3,idy3; char* datas=tmp->imageDataOrigin; long int steps=tmp->widthStep; double v1x=x[1]-x[2], v1y=y[1]-y[2]; double v2x=x[3]-x[2], v2y=y[3]-y[2]; int area=5; int L=8; int B=3; double wasmax=0; for(long int dx1=-area; dx1<=area; dx1++){ for(long int dy1=-area; dy1<=area; dy1++){ double a=angleF(datas,steps,szSrc,x[1]+dx1,y[1]+dy1,-v1x,-v1y,v2x,v2y,L,B); if(a>wasmax){ idx1=dx1; idy1=dy1; wasmax=a; }; };}; wasmax=0; for(long int dx2=-area; dx2<=area; dx2++){ for(long int dy2=-area; dy2<=area; dy2++){ double a=angleF(datas,steps,szSrc,x[2]+dx2,y[2]+dy2,v1x,v1y,v2x,v2y,L,B); if(a>wasmax){ idx2=dx2; idy2=dy2; wasmax=a; }; };}; wasmax=0; for(long int dx3=-area; dx3<=area; dx3++){ for(long int dy3=-area; dy3<=area; dy3++){ double a=angleF(datas,steps,szSrc,x[3]+dx3,y[3]+dy3,v1x,v1y,-v2x,-v2y,L,B); if(a>wasmax){ idx3=dx3; idy3=dy3; wasmax=a; }; };}; double res[7][7]; int K=7; double base_x=x[2]+idx2, base_y=y[2]+idy2; v1x=x[1]-x[2]+idx1-idx2, v1y=y[1]-y[2]+idy1-idy2; v2x=x[3]-x[2]+idx3-idx2, v2y=y[3]-y[2]+idy3-idy2; double vmax=0,vmin=255; for(long int d1=0; d1<K; d1++){ for(long int d2=0; d2<K; d2++){ long int d_x=base_x+(0.5+d1)*v1x/K+(0.5+d2)*v2x/K; long int d_y=base_y+(0.5+d1)*v1y/K+(0.5+d2)*v2y/K; if( d_x<0 || d_x>szSrc.width || d_y<0 || d_y>szSrc.height ){ res[d1][d2]=1000; }else{ long int adr=d_x*3+(szSrc.height-d_y)*steps+2; res[d1][d2]=datas[adr]; }; if( res[d1][d2]>vmax ){ vmax=res[d1][d2]; }; if( res[d1][d2]<vmin ){ vmin=res[d1][d2]; }; };}; for(int d1=0; d1<K; d1++){ for(int d2=0; d2<K; d2++){ res[d1][d2]= res[d1][d2]<(vmax+vmin)/2 ? 1 : 0; if (res[d1][d2] == 0) res[d1][d2] = 1; else res[d1][d2] = 0; }; }; int isGood=1; for(int i=0; i<K; i++){ if( res[0][i]==0 ){ isGood=0; i=K; }; if( res[K-1][i]==0 ){ isGood=0; i=K; }; if( res[i][0]==0 ){ isGood=0; i=K; }; if( res[i][K-1]==0 ){ isGood=0; i=K; }; }; if( res[1][1]+res[5][1]+res[5][5]+res[1][5] != 1 ){ isGood=0; }; if( isGood==1 ){ double tmp[7][7]; for(int d1=0; d1<K; d1++){ for(int d2=0; d2<K; d2++){ int dd1=res[1][1]+res[1][5]==1 ? d1 : K-1-d1; int dd2=res[1][1]+res[5][1]==1 ? d2 : K-1-d2; tmp[d1][d2]=res[dd1][dd2]; };}; for(int d1=0; d1<K; d1++){ for(int d2=0; d2<K; d2++){ int dd1=tmp[1][2]==1 ? d1 : d2; int dd2=tmp[1][2]==1 ? d2 : d1; res[d1][d2]=tmp[dd1][dd2]; };}; int code[20]; for(int i=0; i<20; i++){ code[i]=0; }; long int beacon=0; if( isGood==1 ){ int checkbits=0; for(int i=2; i<=4; i++){ code[i-1]=res[5][i]; }; for(int i=1; i<=5; i++){ code[i+3]=res[4][i]; code[i+8]=res[3][i]; }; for(int i=2; i<=5; i++){ code[i+12]=res[2][i]; }; for(int i=3; i<=4; i++){ code[i+15]=res[1][i]; }; for(int j=0; j<5; j++){ int bits=0; for(int i=0; i<4; i++){ bits = (bits << 1) + code[j*4+i]; }; checkbits = checkbits ^ bits; if( j<4 ){ beacon = (beacon << 4) + bits; }; }; if( checkbits != 13 ){ isGood=0; printf("checkbits=%d\n", checkbits);}; }; if( isGood==1 ){ CvQCodeBeacon* cur=fbeacon; while( cur && cur->next && cur->id != beacon ){ cur=cur->next; }; if( !cur ){ cur=new CvQCodeBeacon(); fbeacon=cur; cur->next=NULL; }else if( cur->id != beacon ){ cur->next=new CvQCodeBeacon(); cur=cur->next; cur->next=NULL; }; cur->id=beacon; cur->x=base_x+(v1x+v2x)/2; cur->y=base_y+(v1y+v2y)/2; cur->bx=base_x; cur->by=base_y; cur->x1=v1x; cur->y1=v1y; cur->x2=v2x; cur->y2=v2y; long double size=sqrt(sqr(v1x+v2x)+sqr(v1y+v2y)); cur->rx=k_front*szDiv2.width/size; cur->ry=((cur->x) - szDiv2.width)*(cur->rx)/(szDiv2.width*k_side); cur->rz=((cur->y) - szDiv2.height)*(cur->rx)/(szDiv2.width*k_side); cur->d=sqrt(sqr(cur->rx)+sqr(cur->ry)+sqr(cur->rz)); cur->d=floor(cur->d*100)/100; printf("beacon=%d\n", cur->id); for(int d1=K-1; d1>=0; d1--){ for(int d2=0; d2<K; d2++) { printf("%d ", (int)res[d1][d2]); } printf("\n"); } }; }; }; }; contours = contours->h_next; }; }; cvReleaseMemStorage( &storage ); cvReleaseImage(&pyr); cvReleaseImage(&tmp); cvReleaseImage(&gray); cvReleaseImage(&tgray); return fbeacon; };
int main(int argc, char *argv[]) {
IplImage* img = 0; int height,width,step,channels; uchar *data; int i,j,k;
if(argc<2){ printf("Usage: main <image-file-name>\n\7"); exit(0); }
// load an image img=cvLoadImage(argv[1]); if(!img){ printf("Could not load image file: %s\n",argv[1]); exit(0); }
// get the image data height = img->height; width = img->width; step = img->widthStep; channels = img->nChannels; data = (uchar *)img->imageData; printf("Processing a %dx%d image with %d channels\n",height,width,channels);
// create a window cvNamedWindow("mainWin", CV_WINDOW_AUTOSIZE); cvMoveWindow("mainWin", 100, 100);
// invert the image //for(i=0;i<height;i++) for(j=0;j<width;j++) for(k=0;k<channels;k++) //data[i*step+j*channels+k]=255-data[i*step+j*channels+k];
mycvGetQCodeBeacons(img, 5, 0.438, 2.813); // show the image cvShowImage("mainWin", img );
// wait for a key cvWaitKey(0);
// release the image cvReleaseImage(&img ); return 0;
} </source>
<source lang="cpp">
- ifndef cvQCodeBeaconsH
- define cvQCodeBeaconsH
//---------------------------------------------------------------------------
- include "cv.h" // includes OpenCV definitions
- include "highgui.h" // includes highGUI definitions
struct CvQCodeBeacon { long int id; long double rx,ry,rz; long double x,y,z; long double d; long double bx,by; long double x1,y1,x2,y2; CvQCodeBeacon* next; }; CvQCodeBeacon* mycvGetQCodeBeacons(IplImage *img, int ThresholdSteps, double k_front, double k_side);
- endif
</source>
Для сборки используется сценарий:
g++ CvQCodeBeacons.cpp -o qcode -I /usr/local/include/opencv/ -L /usr/local/lib -lm -lcv -lhighgui -lcvaux
Использование:
./qcode QCodeBeacon.jpg
Результат: [3]