본문 바로가기

Project/증강현실을 이용한 사천성

경과 시간 계산 및 일정시간이상 일정 범위 안의 좌표에 있으면 클릭


경과 시간 계산은 크게 어렵지 않았다.

void PlayGameForm::OnBnClickedButtonStart()
{
	this->tStartTime = CTime::GetCurrentTime();	// 현재 시간을 얻어온다.
	SetTimer(TIMER, 1000, NULL);				// 1초마다 호출한다.
	this->cameraManager->Create(ComparePoint, this->cameraManager);
	this->cameraManager->threadState = true;
}

void PlayGameForm::OnTimer(UINT_PTR nIDEvent)
{
	if (nIDEvent == CAMERA)
	{
		this->cameraManager->GetCamera().cvQueryFrame_ipl_OriginalImage();
		this->cameraManager->FindRedColor ();
	}

	if (nIDEvent == TIMER)
	{
		this->Timer();
	}

	CDialog::OnTimer(nIDEvent);
}

void PlayGameForm::Timer ()
{
	this->tCurrentTime = CTime::GetCurrentTime();						// 현재 시간을 얻어온다.
	this->tViewTime = this->tCurrentTime - this->tStartTime;			// 차를 구한다.

	this->cHours.Format("%d : ", this->tViewTime.GetHours());			// 시간 추출
	this->cMinutes.Format("%d : ", this->tViewTime.GetMinutes());		// 분 추출
	this->cSeconds.Format("%d", this->tViewTime.GetSeconds());			// 초 추출

	this->cViewTime = this->cHours + this->cMinutes + this->cSeconds;	// 추출한 시, 분, 초 합치기

	this->m_timer.SetWindowTextA((LPCTSTR)(this->cViewTime));			// 출력
}

문제는 화면에서 붉은색이 일정 시간 멈춰 있을때 이벤트를 발생 시키는 것인데,
Thread를 사용해서 이진화된 영상 자체에 접근했다가
동기화 문제로 고생고생 하다가
결국은 이진화 할때마다 사진으로 저장하고, 그 사진 파일을 이용해서
비교하는 방법을 선택하였다.

DWORD ComparePoint(LPVOID param)
{
	CameraManager *cameraManager = (CameraManager*) param;
	int i = 0;
	int j = 0;
	int counter = 0;
	CString directory, fileName;
	IplImage *ipl_gray_Image;
	IplImage *temp_ipl_gray_Image;

	directory.Format("Image\\");
	fileName.Format("grayImage.jpg");

	while (TRUE)
	{
		ipl_gray_Image = cvLoadImage(directory+fileName, CV_LOAD_IMAGE_UNCHANGED);

		if (ipl_gray_Image != NULL)
		{
			// Before Point중심 구하기 Start
			cameraManager->beforePoint = cvPoint (0, 0);
			counter = 0;

			for (i = 0 ; i < ipl_gray_Image->height ; i++)
			{
				for (j = 0 ; j < ipl_gray_Image->widthStep ; j++)
				{
					if ((ipl_gray_Image->imageData[i * ipl_gray_Image->widthStep + j]) != 0)
					{
						cameraManager->beforePoint.x += j;
						cameraManager->beforePoint.y += i;
						counter++;
					}
				}
			}	

			if (counter != 0)
			{
				cameraManager->beforePoint.x = cameraManager->beforePoint.x / counter;
				cameraManager->beforePoint.y = cameraManager->beforePoint.y / counter;
			}
			// Before Point중심 구하기 End

			temp_ipl_gray_Image = cvLoadImage(directory+fileName, CV_LOAD_IMAGE_UNCHANGED);

			if (temp_ipl_gray_Image != NULL)
			{
				// After Point중심 구하기 Start
				cameraManager->afterPoint = cvPoint (0, 0);
				counter = 0;

				for (i = 0 ; i < temp_ipl_gray_Image->height ; i++)
				{
					for (j = 0 ; j < temp_ipl_gray_Image->widthStep ; j++)
					{
						if ((temp_ipl_gray_Image->imageData[i * temp_ipl_gray_Image->widthStep + j]) != 0)
						{
							cameraManager->afterPoint.x += j;
							cameraManager->afterPoint.y += i;
							counter++;
						}
					}
				}

				if (counter != 0)
				{
					cameraManager->afterPoint.x = cameraManager->afterPoint.x / counter;
					cameraManager->afterPoint.y = cameraManager->afterPoint.y / counter;
				}
				// After Point중심 구하기 End

				// Befor Point와 After Point 차이 구하기 Start
				cameraManager->comparePoint = cvPoint(0, 0);
				counter = 0;

				cameraManager->comparePoint.x = abs(cameraManager->afterPoint.x - cameraManager->beforePoint.x);
				cameraManager->comparePoint.y = abs(cameraManager->afterPoint.y - cameraManager->beforePoint.y);
				// Befor Point와 After Point 차이 구하기 End

				// 비교해서 Event 발생
				if (cameraManager->comparePoint.x < CLICK_X || cameraManager->comparePoint.y < CLICK_Y)
				{
					if (cameraManager->frameCounter > FRAMECOUNTER)
					{
						AfxMessageBox("클릭");
						cameraManager->frameCounter = 0;
					}
				}
				else
				{
					cameraManager->frameCounter = 0;				
				}
			}

			cvReleaseImage( &(ipl_gray_Image) );
			cvReleaseImage( &(temp_ipl_gray_Image) );
		}
	}

	cameraManager->threadState = false;

	return FALSE;
}