Exemplo n.º 1
0
//Main tracking Algorithm
void AnalysisModule::larvaFind(uchar * img, int imWidth, int imHeight, int frameInd){

	input = cv::Mat(imHeight,imWidth,CV_8UC1,NULL);
	input.data = img;
	if(output.rows != imHeight | output.cols != imWidth) output.create(imHeight,imWidth,CV_8UC1);
	int nextInd = (index+1)%sampleInd.size();

	//for Profiling
	tic();
		
	sampleInd[nextInd] = frameInd;
	sampleTime[nextInd] = frameInd * frameIntervalMS;

	//On first image, automatically determine threshold level using the Otsu method
	// Minimizes within group variance of thresholded classes.  Should land on the best boundary between backlight and larva
	if(index == -1) threshold = otsuThreshold(img,imWidth*imHeight);
	

	//Can speed this up by applying to a roi bounding box a bit larger than the previous one

	//Simple inverted binary threshold of the image
	cv::threshold(input,output,threshold,255,CV_THRESH_BINARY_INV);  profile[0] = toctic();
	//Detect Contours in the binary image
	cv::findContours(output,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);  profile[1] = toctic();
	
	//No contours detected
	if (contours.size() == 0) {
		return;
	}

	//find contour with largest perimeter length
	double maxLen = 0; int maxInd = -1;
	double cLen;
	for(int i=0; i<contours.size(); i++){
		cLen = cv::arcLength(cv::Mat(contours[i]), false);
		if(cLen >= maxLen){ maxLen = cLen; maxInd = i; };
	}
	
	//Check to make sure that the perimeter is a larva by simple size analysis 
	//(larva should have a certain perimeter length at 8.1um/pixel)
	cLarva[nextInd] = contours[maxInd];
	
	//calculate bounding box
	bBox[nextInd] = cv::boundingRect(cv::Mat(cLarva[nextInd])); profile[2] = toctic();
	
	//Calculate fourier coefficients
	fourierDecompose(cLarva[nextInd],nFourier,fourier[nextInd]);
	centroid[nextInd] = cv::Point2f(fourier[nextInd][0][AX],fourier[nextInd][0][AY]); profile[3] = toctic();

	//Reconstruct the estimated boundary
	fourierReconstruct(fourier[nextInd],cFit,fitRes); profile[4] = toctic();
	
	//Calculate Curvature
	perimeterCurvature(cFit,curve,fitRes/8); profile[5] = toctic();

	//Find head and tail based on curvature minimums (small angle = sharp region)
	findHeadTail(cFit,curve,headTail); 
	head[nextInd] = headTail[0];
	tail[nextInd] = headTail[1]; profile[6] = toctic();

	//Calculate Skeleton
	skeletonCalc(cFit,skeleton,headTail,length[nextInd],neck[nextInd]); profile[7] = toctic();
	

	//Calculate bearing and head angle to bearing
	bodyAngles(tailBearingAngle[nextInd], headToBodyAngle[nextInd], head[nextInd], neck[nextInd], tail[nextInd]); profile[8] = toctic();
	

	//Capture stage position 
	stagePos[nextInd] = cv::Point(gui->stageThread->xpos,gui->stageThread->ypos);
	
	//Keep track of entire history with a sample every 30 frames
	if((nextInd % 30) == 0){
		fullTrack[(fullTrackInd+1)%fullTrack.size()].x = stagePos[nextInd].x/gui->stageThread->tickPerMM_X+centroid[nextInd].x*gui->camThread->umPerPixel/1000.0;
		fullTrack[(fullTrackInd+1)%fullTrack.size()].y = stagePos[nextInd].y/gui->stageThread->tickPerMM_Y+centroid[nextInd].y*gui->camThread->umPerPixel/1000.0;
		fullTrackStim[(fullTrackInd+1)%fullTrack.size()] = binStimMax;
		binStimMax = 0; //updated from stimThread
		fullTrackInd++;
	}
	

	//Calculate Velocities of head and tail
	calcVelocities(nextInd);

	//Spew out profiling info
	//for(int i=0; i<9; i++) qDebug("%d: %.4fms",i,profile[i]*1000);
	//qDebug("\n");
	
	index++;

};
Exemplo n.º 2
0
// Заполнение src->edgeA, src->edgeB src->inCont src->centLine
int correctContour(frGeomStrip* src){
	if(!src->isStrip()){
		return -1;
	}

	src->minX = src->maxX = src->minY = src->maxY = -1;

	// до начала имнимум-максимум - первая точка
	src->minX = src->maxX = ((CvPoint*) cvGetSeqElem(src->stripCont, 0))->x;
	src->minY = src->maxY = ((CvPoint*) cvGetSeqElem(src->stripCont, 0))->y;

	// ищем координаты прямоугольника, описывающего контур
	for( int i=0; i<src->stripCont->total; ++i ) {
		CvPoint* t = (CvPoint*)cvGetSeqElem ( src->stripCont, i );
		src->minX = (t->x < src->minX) ? t->x : src->minX;
		src->maxX = (t->x > src->maxX) ? t->x : src->maxX;
		src->minY = (t->y < src->minY) ? t->y : src->minY;
		src->maxY = (t->y > src->maxY) ? t->y : src->maxY;
	}

	// creating black image with contour highlited with white pixels
	// вспомогательное изображение для отрисовки и "прострела" контура
	IplImage* auxiliaryImage = cvCreateImage( cvSize(src->stripFrame->width, src->stripFrame->height), IPL_DEPTH_8U, 1);
	cvFillImage(auxiliaryImage, 0.0);

	CvRect myROI = src->getROI();

	/*
	if( myROI.x > 0)
		printf("*");
		*/
	// изображение для визуализации работы с гранями
	IplImage* visualImage = cvCreateImage( cvSize(myROI.width , myROI.height), IPL_DEPTH_8U, 3);
	cvFillImage(visualImage, -10.0);

	//сохранили оригинальное РОИ
	CvRect origROI = cvGetImageROI(src->stripFrame );

	// назначаем новое РОИ, чтобы скопировалась только нужная область в картинку visualImage
	cvSetImageROI(src->stripFrame, myROI);
	//	cvCopy(src->stripFrame, visualImage, 0);
	
	//cvShowImage("visual", visualImage);

	// восстановили оригинаьное РОИ
	cvSetImageROI(src->stripFrame, origROI);

	cvDrawContours(auxiliaryImage, src->stripCont, CVX_WHITE, CVX_WHITE, 0, 1);
	
	
	vector<CvPoint> APoints, BPoints, middlePoints; // левые и правые (иногда верхние и нижние) точки границы. заполняются сверху-вниз полосы

	int start = (vertical) ? src->minY + (src->maxY - src->minY) * ((float)HEAD_TAIL_PERCENT/100) : 
							 src->minX + (src->maxX - src->minX) * ((float)HEAD_TAIL_PERCENT/100) ;
	int finish =(vertical) ? src->minY + (src->maxY - src->minY) * (1 - (float)HEAD_TAIL_PERCENT/100) :
							 src->minX + (src->maxX - src->minX) * (1 - (float)HEAD_TAIL_PERCENT/100) ;
	int begin = (vertical) ? src->minX - 1 : src->minY - 1;
	int end	=	(vertical) ? src->maxX + 1 : src->maxY + 1;

	for( int i = start; i < finish; i++){		// Обходим сверху вниз (л-п)	

		for( int j = begin; j < end; j++){		// "стреляем" слева (сверху) до первого не чёрного пикселя
			uchar pix =  (vertical) ? px(auxiliaryImage, j /*- myROI.x*/, i /*- myROI.y*/) : px(auxiliaryImage, i /*- myROI.x*/, j /*- myROI.y*/);
			if( 0 != pix ){	// Первая не чёрная точка в этой строке пикселов
				CvPoint t;
				t.x = (vertical) ? j : i;
				t.y = (vertical) ? i : j;
				APoints.push_back( t );
				break;
			}// if 
		}// for j
		
		for( int j = end; j > begin; j--){ // "стреляем" справа (снизу) до первого не чёрного пикселя
			uchar pix =  (vertical) ? px(auxiliaryImage, j /*- myROI.x*/, i /*- myROI.y*/) : px(auxiliaryImage, i /*- myROI.x*/, j /*- myROI.y*/);
			if( 0 != pix ){	// Первая не чёрная точка в этой строке пикселов
				CvPoint t;
				t.x = (vertical) ? j : i;
				t.y = (vertical) ? i : j;
				BPoints.push_back( t );
				break;
			}// if 
		}// for j
		
		CvPoint t;
		t.x = (vertical) ? (APoints.back().x + BPoints.back().x) / 2 : i;
		t.y = (vertical) ? i : (APoints.back().y + BPoints.back().y) / 2;

		middlePoints.push_back(t);

	}// for i


	vector<CvPoint>::iterator itr;

	itr = APoints.begin();
	while(itr != APoints.end()){
		src->edgeA.push_back(*itr);	
		++itr;
	}

	itr = BPoints.begin();
	while(itr != BPoints.end()){
		src->edgeB.push_back(*itr);
		++itr;
	}

	itr = middlePoints.begin();
	while(itr != middlePoints.end()){
		 src->centLine.push_back(*itr);
		++itr;
	}

	// smooth contours edgeA and edgeB
	smoothContour( src );
	
	src->chordA = chorda(src->edgeA, src->posChordA);
	src->chordB = -chorda(src->edgeB, src->posChordB);

	
	// вывод результата (две грани и центральная линия) на картинку visualImage
		
	// рисуем  левую, правую и среднюю линии

	//printf("S: %d\t", curFrStrip.isStrip() ? 1 : 0);
		if(src->edgeA.size() > 5){
			
			vector<CvPoint>::iterator itr2 = src->edgeA.begin();
			while(itr2 != src->edgeA.end()){
				cvLine( visualImage, cvPoint(itr2->x - myROI.x, itr2->y - myROI.y), cvPoint(itr2->x - myROI.x, itr2->y - myROI.y), CV_RGB(0,0,0));
				++itr2;
			}
			
			vector<CvPoint>::iterator itr3 = src->edgeB.begin();
			while(itr3 != src->edgeB.end()){
				cvLine( visualImage, cvPoint(itr3->x - myROI.x, itr3->y - myROI.y), cvPoint(itr3->x - myROI.x, itr3->y - myROI.y), CV_RGB(0,0,0));
				++itr3;
			}
			
			vector<CvPoint>::iterator itr4 = src->centLine.begin();
			while(itr4 != src->centLine.end()){
				cvLine( visualImage, cvPoint(itr4->x - myROI.x, itr4->y - myROI.y), cvPoint(itr4->x - myROI.x, itr4->y - myROI.y), CV_RGB(0,255,0), 2);
				++itr4;
			}


		}

		FILE* fi;
	#ifdef __UNDIST_PROC__
		if ( src->undistAv == false ) {
	#endif
	#ifdef __DIST_PROC__
		 fi = fopen("chords.txt", "a+");
	#endif
	#ifdef __UNDIST_PROC__
		} else { 
			fi = fopen("undchords.txt", "a+");
		}
	#endif

		CvPoint A1, A2, B1, B2, Ah, Bh; 

		int p1 = (src->edgeA.size()*O_o > H_T_PIX) ? src->edgeA.size()*O_o : H_T_PIX;
		int p2 = (src->edgeA.size()*(1-O_o) < (src->edgeA.size() - H_T_PIX)) ? src->edgeA.size()*(1-O_o) : (src->edgeA.size() - H_T_PIX);

			A1 = cvPoint(src->edgeA[p1].x, src->edgeA[p1].y);
			A2 = cvPoint(src->edgeA[p2].x, src->edgeA[p2].y); 
			B1 = cvPoint(src->edgeB[p1].x, src->edgeB[p1].y);
			B2 = cvPoint(src->edgeB[p2].x, src->edgeB[p2].y);
		
		


		// Рисование хорд

		cvLine(visualImage, cvPoint(A1.x - myROI.x, A1.y - myROI.y) , cvPoint(A2.x - myROI.x, A2.y - myROI.y) , CV_RGB(255,0,0));
			cvLine(visualImage, cvPoint(A1.x - myROI.x, A1.y - myROI.y-3) , cvPoint(A1.x - myROI.x, A1.y - myROI.y+3) , CV_RGB(255,0,0));
			cvLine(visualImage, cvPoint(A2.x - myROI.x, A2.y - myROI.y-3) , cvPoint(A2.x - myROI.x, A2.y - myROI.y+3) , CV_RGB(255,0,0));
		
		cvLine(visualImage, cvPoint(B1.x - myROI.x, B1.y - myROI.y) , cvPoint(B2.x - myROI.x, B2.y - myROI.y) , CV_RGB(255,0,0));
			cvLine(visualImage, cvPoint(B1.x - myROI.x, B1.y - myROI.y-3) , cvPoint(B1.x - myROI.x, B1.y - myROI.y+3) , CV_RGB(255,0,0));
			cvLine(visualImage, cvPoint(B2.x - myROI.x, B2.y - myROI.y-3) , cvPoint(B2.x - myROI.x, B2.y - myROI.y+3) , CV_RGB(255,0,0));
			/*
		cvCircle(visualImage, cvPoint(src->posChordA.x - myROI.x, src->posChordA.y - myROI.y), 2, CV_RGB(255,0,0), 1);
		cvCircle(visualImage, cvPoint(src->posChordB.x - myROI.x, src->posChordB.y - myROI.y), 2, CV_RGB(255,0,0), 1);
		*/
		Ah = heightBase(A1, A2, src->posChordA);
		Bh = heightBase(B1, B2, src->posChordB);
		//cvDrawLine
		cvLine(visualImage, cvPoint(Ah.x - myROI.x, Ah.y - myROI.y), cvPoint(src->posChordA.x - myROI.x, src->posChordA.y - myROI.y), CV_RGB(0,0,0) );
		cvLine(visualImage, cvPoint(Bh.x - myROI.x, Bh.y - myROI.y), cvPoint(src->posChordB.x - myROI.x, src->posChordB.y - myROI.y), CV_RGB(0,0,0) );

		src->head_tail = findHeadTail(src);
		printf( "HT:\t%d\n", src->head_tail );

	//################################# AG code####################
    //chords in mm
		src->chordAmm = chordmm(src->edgeA, src->posChordA, src->cAnch);
		src->chordBmm = -chordmm(src->edgeB, src->posChordB, src->cAnch);
		printf("in mm:\tchords\t%3.2f\t%3.2f\tavg:\t%4.3f\tlen:\t%d\n", src->chordAmm, src->chordBmm, (src->chordAmm + src->chordBmm)/2, /*abs*/(pi2mm(src->edgeA.back(), src->cAnch ).x - pi2mm( src->edgeA.front(), src->cAnch ).x)) ;
		fprintf(fi,"in mm:\tchords\t%3.2f\t%3.2f\tavg:\t%4.3f\tlen:\t%d\tHT:%d\n", src->chordAmm, src->chordBmm, (src->chordAmm + src->chordBmm)/2, abs(pi2mm(src->edgeA.back(), src->cAnch ).x - pi2mm( src->edgeA.front(), src->cAnch ).x), src->head_tail) ;
    //################################# noneAG code####################


	//################################# AG code####################
    //chords in mm
		src->chordAmm = chordmm(src->edgeA, src->posChordA, src->cAnch);
		src->chordBmm = -chordmm(src->edgeB, src->posChordB, src->cAnch);
		printf("in mm:\tchords\t%3.2f\t%3.2f\tavg:\t%4.3f\tlen:\t%d\n", src->chordAmm, src->chordBmm, (src->chordAmm + src->chordBmm)/2, abs(pi2mm(src->edgeA.back(), src->cAnch ).x - pi2mm( src->edgeA.front(), src->cAnch ).x)) ;
       fprintf(fi,"in mm:\tchords\t%3.2f\t%3.2f\tavg:\t%4.3f\tlen:\t%d\n", src->chordAmm, src->chordBmm, (src->chordAmm + src->chordBmm)/2, abs(pi2mm(src->edgeA.back(), src->cAnch ).x - pi2mm( src->edgeA.front(), src->cAnch ).x)) ;
    //################################# noneAG code####################


		//printf("chords %3.2f:%3.2f; avg: %4.3f; len: %d \n", src->chordA, src->chordB, (src->chordA + src->chordB)/2, abs(src->edgeA.back().x - src->edgeA.front().x) );

	#ifdef __DEBUG_CHORDS__
		fprintf(fi,"in pi:\tchords\t%3.2f\t%3.2f\tavg:\t%4.3f\tlen:\t%d\n", src->chordA, src->chordB, (src->chordA + src->chordB)/2, abs(src->edgeA.back().x - src->edgeA.front().x)) ; 
		printf("in pi:\tchords\t%3.2f\t%3.2f\tavg:\t%4.3f\tlen:\t%d\n", src->chordA, src->chordB, (src->chordA + src->chordB)/2, abs(src->edgeA.back().x - src->edgeA.front().x)) ; 
	#endif
		
		fclose(fi);
		//////////////////////////////////////

	#ifdef __UNDIST_PROC__
		if ( src->undistAv == false ) {
	#endif
	#ifdef __DIST_PROC__
			cvShowImage("visual", visualImage);
	//	cvShowImage("visual", auxiliaryImage);
	#endif
	#ifdef __UNDIST_PROC__
		} else { 
			cvShowImage("undVisual", visualImage);
		}
	#endif
			
	// removing binaryImage from memory
	cvReleaseImage(&auxiliaryImage);
	cvReleaseImage(&visualImage);

	return 0;
}