ReturnType ZoomInOut::onExecute() { // 영상을 Inport로부터 취득 opros_any *pData = ImageIn.pop(); RawImage result; if(pData != NULL){ // 포트로 부터 이미지 취득 RawImage Image = ImageIn.getContent(*pData); RawImageData *RawImage = Image.getImage(); // 현재영상의 크기를 취득 m_in_width = RawImage->getWidth(); m_in_height = RawImage->getHeight(); // 원본영상의 이미지영역 확보 if(m_orig_img == NULL){ m_orig_img = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 3); } if(m_result_img == NULL){ m_pre_zoom = m_zoom; m_result_img = cvCreateImage(cvSize((int)(m_in_width * m_zoom), (int)(m_in_height * m_zoom)), IPL_DEPTH_8U, 3); } // 영상에 대한 정보를 확보!memcpy memcpy(m_orig_img->imageData, RawImage->getData(), RawImage->getSize()); cvResize(m_orig_img, m_result_img, m_interpolation); // RawImage의 이미지 포인터 변수 할당 RawImageData *pimage = result.getImage(); // 입력된 이미지 사이즈 및 채널수로 로 재 설정 pimage->resize(m_result_img->width, m_result_img->height, m_result_img->nChannels); // 영상의 총 크기(pixels수) 취득 int size = m_result_img->width * m_result_img->height * m_result_img->nChannels; // 영상 데이터로부터 영상값만을 할당하기 위한 변수 unsigned char *ptrdata = pimage->getData(); // 현재 프레임 영상을 사이즈 만큼 memcpy memcpy(ptrdata, m_result_img->imageData, size); // 포트아웃 opros_any mdata = result; ImageOut.push(result);//전달 delete pData; } return OPROS_SUCCESS; }
ReturnType ErodeDilate::onExecute() { // 영상을 Inport로부터 취득 opros_any *pData = ImageIn.pop(); RawImage result; if(pData != NULL){ // 포트로 부터 이미지 취득 RawImage Image = ImageIn.getContent(*pData); RawImageData *RawImage = Image.getImage(); // 현재영상의 크기를 취득 m_in_width = RawImage->getWidth(); m_in_height = RawImage->getHeight(); // 원본영상의 이미지영역 확보 if(m_orig_img == NULL){ m_orig_img = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 3); } if(m_gray_img == NULL){ m_gray_img = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 1); } if(m_result_img == NULL){ m_result_img = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 3); } // 영상에 대한 정보를 확보!memcpy memcpy(m_orig_img->imageData, RawImage->getData(), RawImage->getSize()); if(m_RGB_mode == "Gray"){ // m_RGB_mode:1 흑백 // 컬러영상을 그레이스케일로 변환 cvCvtColor( m_orig_img, m_gray_img, CV_RGB2GRAY ); // 그레이이미지(1채널)을 3채널로 변경, 팽창침식연산위해 다시 m_image_buff에 저장 cvMerge(m_gray_img, m_gray_img, m_gray_img, NULL, m_orig_img); } if(m_Change_mode == "Erode"){ // m_change_mode:Erode 침식 cvErode(m_orig_img, m_result_img, NULL, m_Repeat_count); }else if(m_Change_mode == "Dilate"){ // m_change_mode:Dilate 팽창 cvDilate(m_orig_img, m_result_img, NULL, m_Repeat_count); }else{ cvCopy(m_orig_img, m_result_img); } // RawImage의 이미지 포인터 변수 할당 RawImageData *pimage = result.getImage(); // 입력된 이미지 사이즈 및 채널수로 로 재 설정 pimage->resize(m_result_img->width, m_result_img->height, m_result_img->nChannels); // 영상의 총 크기(pixels수) 취득 int size = m_result_img->width * m_result_img->height * m_result_img->nChannels; // 영상 데이터로부터 영상값만을 할당하기 위한 변수 unsigned char *ptrdata = pimage->getData(); // 현재 프레임 영상을 사이즈 만큼 memcpy memcpy(ptrdata, m_result_img->imageData, size); // 포트아웃 opros_any mdata = result; ImageOut.push(result);//전달 delete pData; } return OPROS_SUCCESS; }
ReturnType HandsMotionTracking::onExecute() { // 영상을 Inport로부터 취득 opros_any *pData = ImageIn.pop(); RawImage result; //아웃 데이터 std::vector<PositionDataType> data; if(pData != NULL){ // 포트로 부터 이미지 취득 RawImage Image = ImageIn.getContent(*pData); RawImageData *RawImage = Image.getImage(); // 현재영상의 크기를 취득 m_in_width = RawImage->getWidth(); m_in_height = RawImage->getHeight(); // 메모리 한번 해제해주고 if(m_image_buff != NULL) cvReleaseImage(&m_image_buff); if(m_image_dest != NULL) cvReleaseImage(&m_image_dest); if(m_image_dest2 != NULL) cvReleaseImage(&m_image_dest2); if(m_image_th != NULL) cvReleaseImage(&m_image_th); if(m_image_th2 != NULL) cvReleaseImage(&m_image_th2); // 이미지용 메모리 할당 m_image_buff = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 3);//원본 이미지 m_image_dest = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 3); m_image_dest2 = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 3); m_image_th = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 1);//영역 추출 이미지 m_image_th2 = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 1);//영역 추출 이미지 if(!video_flag) { std::string cpath = getProperty("opros.component.dir"); std::string file = getProperty("VideoFile"); if (file == "") file = "sample.avi"; std::string path = cpath + file; m_video = NULL; m_video = cvCreateFileCapture(path.c_str()); //비디오 video_flag = true;// 비디오가 계속 새로 재생됨을 방지 } // 영상에 대한 정보를 확보!memcpy memcpy(m_image_buff->imageData, RawImage->getData(), RawImage->getSize()); // 출력용 cvCopy(m_image_buff, m_image_dest, 0); // 색상 분리용 이미지 IplImage* m_image_YCrCb = cvCreateImage(cvGetSize(m_image_buff), IPL_DEPTH_8U, 3); IplImage* m_Y = cvCreateImage(cvGetSize(m_image_buff), IPL_DEPTH_8U, 1); IplImage* m_Cr = cvCreateImage(cvGetSize(m_image_buff), IPL_DEPTH_8U, 1); IplImage* m_Cb = cvCreateImage(cvGetSize(m_image_buff), IPL_DEPTH_8U, 1); cvCvtColor(m_image_buff, m_image_YCrCb, CV_RGB2YCrCb); //RGB - > YCrCV 변환 cvSplit(m_image_YCrCb, m_Y, m_Cr, m_Cb, NULL); //채널 분리 //추출이 필요한 영역 픽셀 데이터 저장 변수 unsigned char m_Cr_val = 0; unsigned char m_Cb_val = 0; // 살색추출 for(int i=0;i<m_image_buff->height;i++) { for(int j=0;j<m_image_buff->width;j++) { //Cr 영역과 Cb 영역 추출 m_Cr_val = (unsigned char)m_Cr->imageData[i*m_Cr->widthStep+j]; m_Cb_val = (unsigned char)m_Cb->imageData[i*m_Cb->widthStep+j]; //살색에 해당하는 영역인지 검사 if( (77 <= m_Cr_val) && (m_Cr_val <= 127) && (133 <= m_Cb_val) && (m_Cb_val <= 173) ) { // 살색부분은 하얀색 m_image_buff->imageData[i*m_image_buff->widthStep+j*3+0] = (unsigned char)255; m_image_buff->imageData[i*m_image_buff->widthStep+j*3+1] = (unsigned char)255; m_image_buff->imageData[i*m_image_buff->widthStep+j*3+2] = (unsigned char)255; } else { // 나머지는 검정색 m_image_buff->imageData[i*m_image_buff->widthStep+j*3+0]= 0; m_image_buff->imageData[i*m_image_buff->widthStep+j*3+1]= 0; m_image_buff->imageData[i*m_image_buff->widthStep+j*3+2]= 0; } } } //살색 추출한 영상을 이진화 cvCvtColor(m_image_buff, m_image_th, CV_RGB2GRAY); //잡영 제거를 위한 연산 cvDilate (m_image_th, m_image_th, NULL, 2);//팽창 cvErode (m_image_th, m_image_th, NULL, 2);//침식 //변수 및 이미지 메모리 초기화 int temp_num = 0; int StartX , StartY, EndX , EndY; int nNumber = 0; m_nThreshold = 100; if( m_rec_out != NULL ) { delete m_rec_out; m_rec_out = NULL; m_nBlobs_out = _DEF_MAX_BLOBS; } else { m_rec_out = NULL; m_nBlobs_out = _DEF_MAX_BLOBS; } if( m_image_th2 != NULL ) cvReleaseImage( &m_image_th2 ); //레이블링 할 영상 따로 생성 m_image_th2 = cvCloneImage( m_image_th ); //레이블링 할 이미지의 크기 저장 int nWidth = m_image_th2->width; int nHeight = m_image_th2->height; //해당 영상 크기만큼 버프 설정 unsigned char* tmpBuf = new unsigned char [nWidth * nHeight]; for(int j=0; j<nHeight ;j++) for(int i=0; i<nWidth ;i++) //전 픽셀 순회 tmpBuf[j*nWidth+i] = (unsigned char)m_image_th2->imageData[j*m_image_th2->widthStep+i]; ////// 레이블링을 위한 포인트 초기화 m_vPoint_out = new Visited [nWidth * nHeight]; for(int nY = 0; nY < nHeight; nY++) { for(int nX = 0; nX < nWidth; nX++) { m_vPoint_out[nY * nWidth + nX].bVisitedFlag = FALSE; m_vPoint_out[nY * nWidth + nX].ptReturnPoint.x = nX; m_vPoint_out[nY * nWidth + nX].ptReturnPoint.y = nY; } } ////// 레이블링 수행 for(int nY = 0; nY < nHeight; nY++) { for(int nX = 0; nX < nWidth; nX++) { if(tmpBuf[nY * nWidth + nX] == 255) // Is this a new component?, 255 == Object { temp_num++; tmpBuf[nY * nWidth + nX] = temp_num; StartX = nX, StartY = nY, EndX = nX, EndY= nY; __NRFIndNeighbor(tmpBuf, nWidth, nHeight, nX, nY, &StartX, &StartY, &EndX, &EndY, m_vPoint_out); if(__Area(tmpBuf, StartX, StartY, EndX, EndY, nWidth, temp_num) < m_nThreshold) { for(int k = StartY; k <= EndY; k++) { for(int l = StartX; l <= EndX; l++) { if(tmpBuf[k * nWidth + l] == temp_num) tmpBuf[k * nWidth + l] = 0; } } --temp_num; if(temp_num > 250) temp_num = 0; } } } } // 포인트 메모리 해제 delete m_vPoint_out; //결과 보존 nNumber = temp_num; //레이블링 수만큼 렉트 생성 if( nNumber != _DEF_MAX_BLOBS ) m_rec_out = new CvRect [nNumber]; //렉트 만들기 if( nNumber != 0 ) DetectLabelingRegion(nNumber, tmpBuf, nWidth, nHeight,m_rec_out); for(int j=0; j<nHeight; j++) for(int i=0; i<nWidth ; i++) m_image_th2->imageData[j*m_image_th2->widthStep+i] = tmpBuf[j*nWidth+i]; delete tmpBuf; //레이블링 수 보존 m_nBlobs_out = nNumber; //레이블링 영역 거르기 int nMaxWidth = m_in_height * 9 / 10; // 영상 가로 전체 크기의 90% 이상인 레이블은 제거 int nMaxHeight = m_in_width * 9 / 10; // 영상 세로 전체 크기의 90% 이상인 레이블은 제거 //최소영역과 최대영역 지정- 화면 크기에 영향 받음.. _BlobSmallSizeConstraint( 5, 150, m_rec_out, &m_nBlobs_out); _BlobBigSizeConstraint(nMaxWidth, nMaxHeight,m_rec_out, &m_nBlobs_out); //앞으로 쓸 메모리 등록 storage1 = cvCreateMemStorage(0); storage2 = cvCreateMemStorage(0); //변수 초기화 CvPoint point; CvSeq* seq[10]; CvSeq* hull; CvPoint end_pt; CvPoint center; //내보낼 데이터 초기화 outData[0].x = 0, outData[0].y = 0; outData[1].x = 0, outData[1].y = 0; outData[2].x = 0, outData[2].y = 0; int num = 0; int temp_x = 0; int temp_y = 0; int rect = 0; //만일을 대비하여 준비한 시퀸스 배열의 크기를 초과하지 않도록 조절 //일단 한곳에서만 영상이 나오도록 조절.. if(m_nBlobs_out > 1) { m_nBlobs_out = 1; } //레이블링 영역 내의 처리 시작 for( int i=0; i < m_nBlobs_out; i++ ) { //사각형 그리기에 필요한 두점 저장 CvPoint pt1 = cvPoint( m_rec_out[i].x, m_rec_out[i].y ); CvPoint pt2 = cvPoint( pt1.x + m_rec_out[i].width,pt1.y + m_rec_out[i].height ); // 컬러값 설정 CvScalar color = cvScalar( 0, 0, 255 ); //레이블 사각형 그리기 - 확인용 //cvDrawRect( m_image_dest, pt1, pt2, color); //레이블을 관심영역으로 지정할 이미지 생성 temp_mask = cvCreateImage(cvSize(m_rec_out[i].width, m_rec_out[i].height),8,1); temp_mask2 = cvCreateImage(cvSize(m_rec_out[i].width, m_rec_out[i].height),8,1); //관심영역 지정 cvSetImageROI(m_image_th, m_rec_out[i]); //관심영역 추출 cvCopy(m_image_th, temp_mask, 0); //관심영역 해제 cvResetImageROI(m_image_th); //관심영역 내의 오브젝트 처리를 위한 시퀸스 생성 seq[i] = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2,sizeof(CvContour),sizeof(CvPoint), storage1); //관심영역에서 추출한이미지의 흰색 픽셀값으로 시퀸스 생성 for(int j =0; j < temp_mask ->height ; j++) { for(int k = 0; k < temp_mask ->width; k++) { if((unsigned char)temp_mask->imageData[j*temp_mask->widthStep+k] == 255) { point.x = k; //흰색 픽셀 x좌표 저장 point.y = j; //흰색 픽셀 y좌표 저장 cvSeqPush(seq[i], &point); //시퀸스 구조체에 해당 좌표 삽입 temp_x += point.x; //좌표 누적 temp_y += point.y; //좌표 누적 num++; //픽셀 수 카운트 } } } //좌표 초기화 point.x = 0; point.y = 0; end_pt.x = 0; end_pt.y = 0; center.x = 0; center.y = 0; CvPoint dist_pt; //중심점과의 최대거리를 찾을 컨백스헐 저장 double fMaxDist = 0; //중심점과의 최대거리 저장 double fDist = 0; //거리계산에 사용 //중심점 찾기 - 픽셀의 평균값 찾기 if(num != 0) { center.x = (int)temp_x/num; //평균 좌표값 구하기 center.y = (int)temp_y/num; //평균 좌표값 구하기 } //관심영역 설정 cvSetImageROI(m_image_dest, m_rec_out[i]); /////////컨백스헐 그리기//////// if(seq[i]->total !=0) { //컨백스헐 구하기 hull = cvConvexHull2(seq[i], 0, CV_COUNTER_CLOCKWISE, 0); point = **CV_GET_SEQ_ELEM(CvPoint*, hull,hull->total-1); //구한 컨백스헐 라인으로 그리기 for(int x = 0; x < hull->total; x++) { CvPoint hull_pt = **CV_GET_SEQ_ELEM(CvPoint*, hull,x); //컨백스헐 라인 그리기 //cvLine(m_image_dest, point, hull_pt, CV_RGB(255, 255, 0 ),2, 8); point = hull_pt; //최대 거리 구하기 dist_pt = **CV_GET_SEQ_ELEM(CvPoint*, hull,x); fDist = sqrt((double)((center.x - dist_pt.x) * (center.x - dist_pt.x) + (center.y - dist_pt.y) * (center.y - dist_pt.y))); if(fDist > fMaxDist) { max_pt = dist_pt; fMaxDist = fDist; } } } //중심점그리기 cvCircle(m_image_dest,center,5, CV_RGB(0,0,255), 5); //내보낼 중심점 데이터 저장 outData[0].x = center.x; outData[0].y = center.y; ////////마스크 만들기/////// //중심점을 기준으로 그릴 마스크 이미지 생성 circle_mask = cvCreateImage(cvGetSize(temp_mask), 8, 1); //바탕은 검은색으로 cvSetZero(circle_mask); //흰색 원 - 손 영상과의 연산을 위해 바이너리 이미지에 그리기 int radi = (int)m_rec_out[i].height/2.9; // 원 크기 수동조절.. //흰색 원과 흰색 네모로 구성된 마스크 영상 생성을 위한 그리기 cvCircle(circle_mask, center, radi, CV_RGB(255,255,255),CV_FILLED); cvDrawRect(circle_mask, cvPoint(center.x - radi, center.y),cvPoint(center.x + radi, pt2.y), CV_RGB(255,255,255),CV_FILLED); //마스크 추출 cvSub(temp_mask, circle_mask, temp_mask, 0); ///////관심영역 레이블링 - 손가락 끝 추출////// //변수 및 이미지 메모리 초기화 int temp_num_in = 0; int StartX_in , StartY_in, EndX_in , EndY_in; int nNumber_in = 0; m_nThreshold_in = 10; if( m_rec_in != NULL ) { delete m_rec_in; m_rec_in = NULL; m_nBlobs_in = _DEF_MAX_BLOBS; } else { m_rec_in = NULL; m_nBlobs_in = _DEF_MAX_BLOBS; } if( temp_mask2 != NULL ) cvReleaseImage( &temp_mask2 ); temp_mask2 = cvCloneImage( temp_mask ); //들어온 이미지의 크기 저장 int nWidth = temp_mask2->width; int nHeight = temp_mask2->height; //영상 크기만큼 버프 설정 unsigned char* tmpBuf_in = new unsigned char [nWidth * nHeight]; for(int j=0; j<nHeight ;j++) for(int i=0; i<nWidth ;i++) //전 픽셀 순회 tmpBuf_in[j*nWidth+i] = (unsigned char)temp_mask2->imageData[j*temp_mask2->widthStep+i]; /////// 레이블링을 위한 포인트 초기화 //////// m_vPoint_in = new Visited [nWidth * nHeight]; for(int nY = 0; nY < nHeight; nY++) { for(int nX = 0; nX < nWidth; nX++) { m_vPoint_in[nY * nWidth + nX].bVisitedFlag = FALSE; m_vPoint_in[nY * nWidth + nX].ptReturnPoint.x = nX; m_vPoint_in[nY * nWidth + nX].ptReturnPoint.y = nY; } } ////레이블링 수행 for(int nY = 0; nY < nHeight; nY++) { for(int nX = 0; nX < nWidth; nX++) { if(tmpBuf_in[nY * nWidth + nX] == 255) // Is this a new component?, 255 == Object { temp_num_in++; tmpBuf_in[nY * nWidth + nX] = temp_num_in; StartX_in = nX, StartY_in = nY, EndX_in = nX, EndY_in= nY; __NRFIndNeighbor(tmpBuf_in, nWidth, nHeight, nX, nY, &StartX_in, &StartY_in, &EndX_in, &EndY_in,m_vPoint_in); if(__Area(tmpBuf_in, StartX_in, StartY_in, EndX_in, EndY_in, nWidth, temp_num_in) < m_nThreshold_in) { for(int k = StartY_in; k <= EndY_in; k++) { for(int l = StartX_in; l <= EndX_in; l++) { if(tmpBuf_in[k * nWidth + l] == temp_num_in) tmpBuf_in[k * nWidth + l] = 0; } } --temp_num_in; if(temp_num_in > 250) temp_num_in = 0; } } } } // 포인트 메모리 해제 delete m_vPoint_in; //레이블링 수 보존 nNumber_in = temp_num_in; if( nNumber_in != _DEF_MAX_BLOBS ) m_rec_in = new CvRect [nNumber_in]; if( nNumber_in != 0 ) DetectLabelingRegion(nNumber_in, tmpBuf_in, nWidth, nHeight,m_rec_in); for(int j=0; j<nHeight; j++) for(int i=0; i<nWidth ; i++) temp_mask2->imageData[j*temp_mask2->widthStep+i] = tmpBuf_in[j*nWidth+i]; delete tmpBuf_in; m_nBlobs_in = nNumber_in; //최소영역과 최대영역 설정 _BlobSmallSizeConstraint( 5, 5, m_rec_in, &m_nBlobs_in); _BlobBigSizeConstraint( temp_mask2->width, temp_mask2->height,m_rec_in, &m_nBlobs_in); //선언 및 초기화 CvPoint center_in; CvPoint point_in; point_in.x = 0; point_in.y = 0; center_in.x = 0; center_in.x = 0; CvSeq* seq_in[20]; //준비한 시퀸스 배열크기를 초과하지 않도록 조절 if(m_nBlobs_in > 20) { m_nBlobs_in =20; } for( int ni =0; ni < m_nBlobs_in; ni++ ) { //사각형 그리기에 필요한 두 점 저장 CvPoint pt1 = cvPoint( m_rec_in[ni].x, m_rec_in[ni].y ); CvPoint pt2 = cvPoint( pt1.x + m_rec_in[ni].width,pt1.y + m_rec_in[ni].height ); //색상값 설정 CvScalar color = cvScalar( 255,0 , 255 ); //레이블 사각형 그리기 //cvDrawRect( m_image_dest, pt1, pt2, color); //처리할 손끝 마스크 생성할 메모리 할당 in_mask = cvCreateImage(cvSize(m_rec_in[ni].width, m_rec_in[ni].height),8,1); //관심영역 설정 cvSetImageROI(temp_mask, m_rec_in[ni]); //필요한 영역 복사 cvCopy(temp_mask, in_mask, 0); //관심영역 해제 cvResetImageROI(temp_mask); //관심영역 내의 오브젝트 처리를 위한 시퀸스 생성 seq_in[ni] = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2,sizeof(CvContour),sizeof(CvPoint), storage2); //초기화 int temp_x_in = 0; int temp_y_in = 0; int num_in = 0; //관심영역에서 추출한이미지의 흰색 픽셀값으로 시퀸스 생성 for(int j =0; j < in_mask ->height ; j++) { for(int k = 0; k < in_mask ->width; k++) { if((unsigned char)in_mask->imageData[j*in_mask->widthStep+k] == 255) { point_in.x = k; //흰색 픽셀 x좌표 저장 point_in.y = j; //흰색 픽셀 y좌표 저장 cvSeqPush(seq_in[ni], &point_in); //시퀸스 구조체에 해당 좌표 삽입 temp_x_in += point_in.x; //좌표 누적 temp_y_in += point_in.y; //좌표 누적 num_in++; //픽셀 수 카운트 } } } //초기화 max_pt_in.x = 0; max_pt_in.y = 0; double fMaxDist_in = 0; double fDist_in = 0; //중심점 찾기 - 픽셀의 평균값 찾기 if(num_in != 0) { center_in.x = (int)temp_x_in/num_in + pt1.x; //평균 좌표값 구하기 center_in.y = (int)temp_y_in/num_in + pt1.y; //평균 좌표값 구하기 } //우선 끝점이 2개일때만.. if(m_nBlobs_in == 2) { //초기화 finger_pt[ni].x = NULL; finger_pt[ni].y = NULL; finger_pt[ni].x = NULL; finger_pt[ni].y = NULL; if(seq_in[ni]->total !=0) { //컨백스헐 구하기 - 윤곽선의 좌표 정보 겟 CvSeq* hull_in = cvConvexHull2(seq_in[ni], 0, CV_COUNTER_CLOCKWISE, 0); //point_in = **CV_GET_SEQ_ELEM(CvPoint*, hull_in,hull_in->total-1); //구한 컨백스헐 라인으로 그리기 for(int nx = 0; nx < hull_in->total; nx++) { CvPoint hull_pt_in = **CV_GET_SEQ_ELEM(CvPoint*, hull_in,nx); hull_pt_in.x = hull_pt_in.x + pt1.x; hull_pt_in.y = hull_pt_in.y + pt1.y; //중심점과 해당영역의 컨백스 헐 지점간의 거리 계산 fDist_in = sqrt((double)((center.x - hull_pt_in.x) * (center.x - hull_pt_in.x) + (center.y - hull_pt_in.y) * (center.y - hull_pt_in.y))); //거리가 먼 점 찾기 if(fDist_in > fMaxDist_in) { max_pt_in = hull_pt_in; fMaxDist_in = fDist_in; } } } //최대점 보존 finger_pt[ni].x = max_pt_in.x ; finger_pt[ni].y = max_pt_in.y ; //관심영역 해제할 경우의 값으로 보정 finger_pt[ni].x = finger_pt[ni].x + m_rec_out[i].x; finger_pt[ni].y = finger_pt[ni].y + m_rec_out[i].y; }
ReturnType Rotate::onExecute() { // 영상을 Inport로부터 취득 opros_any *pData = ImageIn.pop(); RawImage result; if(pData != NULL){ // 포트로 부터 이미지 취득 RawImage Image = ImageIn.getContent(*pData); RawImageData *RawImage = Image.getImage(); // 현재영상의 크기를 취득 m_in_width = RawImage->getWidth(); m_in_height = RawImage->getHeight(); // 원본영상의 이미지영역 확보 if(m_orig_img == NULL){ m_orig_img = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 3); } if(m_trans_img == NULL){ m_trans_img = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 3); } if(m_result_img == NULL){ m_result_img = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 3); } // 영상에 대한 정보를 확보!memcpy memcpy(m_orig_img->imageData, RawImage->getData(), RawImage->getSize()); //*************************회전 // 회전 중심 위치 설정 CvPoint2D32f center = cvPoint2D32f( m_orig_img->width/2.0, m_orig_img->height/2.0); // 회전각도에 따른 행렬생성 cv2DRotationMatrix( center, m_angle, 1.0, m_rotate_mat ); // cv2DRotationMatrix( center, 50.0, 1.0, m_rotate_mat ); // 이미지회전 cvWarpAffine( m_orig_img, m_result_img, m_rotate_mat, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(0)); // RawImage의 이미지 포인터 변수 할당 RawImageData *pimage = result.getImage(); // 입력된 이미지 사이즈 및 채널수로 로 재 설정 pimage->resize(m_result_img->width, m_result_img->height, m_result_img->nChannels); // 영상의 총 크기(pixels수) 취득 int size = m_result_img->width * m_result_img->height * m_result_img->nChannels; // 영상 데이터로부터 영상값만을 할당하기 위한 변수 unsigned char *ptrdata = pimage->getData(); // 현재 프레임 영상을 사이즈 만큼 memcpy memcpy(ptrdata, m_result_img->imageData, size); // 포트아웃 // opros_any mdata = result; ImageOut.push(result);//전달 delete pData; } return OPROS_SUCCESS; }
ReturnType ColorTracking::onExecute() { // 영상을 Inport로부터 취득 opros_any *pData = ImageIn.pop(); RawImage result; // 데이터 포트 백터 std::vector<PositionDataType> data; if(pData != NULL){ // 포트로 부터 이미지 취득 RawImage Image = ImageIn.getContent(*pData); RawImageData *RawImage = Image.getImage(); // 현재영상의 크기를 취득 m_in_width = RawImage->getWidth(); m_in_height = RawImage->getHeight(); // 원본영상의 이미지영역 확보 if(m_orig_img == NULL){ m_orig_img = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 3); } if(m_dest_img == NULL){ m_dest_img = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 3); } if(m_hsv_img == NULL){ m_hsv_img = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 3); } if(m_gray_img == NULL){ m_gray_img = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 1); } //영상에 대한 정보를 확보!memcpy memcpy(m_orig_img->imageData, RawImage->getData(), RawImage->getSize()); //HSV변환 cvCvtColor(m_orig_img, m_hsv_img, CV_BGR2HSV); //hsv 영역 축소 후, 설정값에 따라 해당 영역 이진 영상 추출 color_config(m_hsv_img, m_color); //영상정리 image_filter(m_gray_img); //검출 갯수 담을 변수 초기화 circle_cnt = 0; rect_cnt = 0; //검출된 원을 위한 메모리 공간 할당 storage0 = cvCreateMemStorage(0); //원 그리기 draw_circle(m_gray_img); //사각형 그리기 draw_square(m_gray_img); //// DataOut //한가지라도 검출되면 if(circles || rects != NULL) { //원 데이터가 존재함 if(circles) { //원의 갯수만큼 for(int k = 0; k < circles->total; k++) { float* cir; int circle_x, circle_y; double radi; //검출된 원을 저장한 circles에서 원의 파라미터를 cir에 저장 //원의 중심 좌표 및 반지름이 배열에 순서대로 저장됨 cir = (float*)cvGetSeqElem(circles, k); //검출된 원을 저장한 circles에서 원의 파라미터를 cir에 저장 //원의 중심 좌표 및 반지름이 배열에 순서대로 저장됨 circle_x = cvRound(cir[0]); //중심점 x 좌표 circle_y = cvRound(cir[1]); //중심점 y 좌표 radi = (double)cvRound(cir[2]); //반지름 PositionDataType base; base.setName("circle"); base.setX(circle_x); base.setY(circle_y); base.setRadian(radi); base.setHeight(NULL); base.setWidth(NULL); data.push_back(base); } } //사각형 데이터가 존재함 if(rects != NULL) { for(int j = 0; j < rect_cnt; j++) { int rect_x, rect_y, rect_width, rect_height; rect_x = rects[j].x; rect_y = rects[j].y; rect_width = rects[j].width; rect_height = rects[j].height; PositionDataType base; base.setName("rectangle"); base.setX(rect_x); base.setY(rect_y); base.setHeight(rect_height); base.setWidth(rect_width); base.setRadian(NULL); data.push_back(base); } } PositionOut.push(data); } //// ImageOut // RawImage의 이미지 포인터 변수 할당 RawImageData *pimage = result.getImage(); // 입력된 이미지 사이즈 및 채널수로 로 재 설정 pimage->resize(m_orig_img->width, m_orig_img->height, m_orig_img->nChannels); // 영상의 총 크기(pixels수) 취득 int size = m_orig_img->width * m_orig_img->height * m_orig_img->nChannels; // 영상 데이터로부터 영상값만을 할당하기 위한 변수 unsigned char *ptrdata = pimage->getData(); // 현재 프레임 영상을 사이즈 만큼 memcpy memcpy(ptrdata, m_orig_img->imageData, size); // 포트아웃 opros_any mdata = result; ImageOut.push(result);//전달 delete pData; } return OPROS_SUCCESS; }
ReturnType FrequencyFilter::onExecute() { // 영상을 Inport로부터 취득 opros_any *pData = ImageIn.pop(); RawImage result; if(pData != NULL) { // 포트로 부터 이미지 취득 RawImage Image = ImageIn.getContent(*pData); RawImageData *RawImage = Image.getImage(); // 현재영상의 크기를 취득 m_in_width = RawImage->getWidth(); m_in_height = RawImage->getHeight(); // 받은 영상의 2의 승수임을 확인 if(!Check2Square(m_in_width) || !Check2Square(m_in_height)) { std::cout << "This image is not a multifplier of 2" << std::endl; return OPROS_BAD_INPUT_PARAMETER; } // 받은 영상의 가로 세로 사이즈가 같은지 확인 if(m_in_width != m_in_height) { std::cout << "Size(width and height) of Image is not equal" << std::endl; return OPROS_BAD_INPUT_PARAMETER; } // 원본영상의 이미지영역 확보 if(m_orig_img == NULL) { m_orig_img = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 3); } // 바이너리 영상영역의 확보 if(m_gray_img == NULL) { m_gray_img = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 1); } // 수행결과 영상영역의 확보 if(m_result_img == NULL) { m_result_img = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 1); } // 출력결과 영상영역의 확보 if(m_final_img == NULL) { m_final_img = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 3); } // Re영역 영상영역의 확보(실수) if(m_image_Re == NULL) { m_image_Re = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_32F, 1); } // Im영역 영상영역의 확보(허수) if(m_image_Im == NULL) { m_image_Im = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_32F, 1); } // 주파수 변환 영상영역의 확보. if(m_pDFT_A == NULL) { m_pDFT_A = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_32F, 2); } // 영상에 대한 정보를 확보!memcpy memcpy(m_orig_img->imageData, RawImage->getData(), RawImage->getSize()); // 둘다 none 이 아니거나, 둘중에 하나가 none 일경우 if((m_low_Pass_Filtering != "none" || m_high_Pass_Filtering != "none") && (m_low_Pass_Filtering == "none" || m_high_Pass_Filtering == "none")) { // 입력 받은 영상을 이진화 시킴 cvCvtColor( m_orig_img, m_gray_img, CV_BGR2GRAY ); // 주파수영역으로의 작업을 위한 깊이 정보 변경 cvConvertScale(m_gray_img, m_image_Re); // 8U -> 32F // m_image_Im의 초기화 cvZero(m_image_Im); // shift center // 입력영상을 실수부로 변환한 이미지가 홀수인 화소의 부호를 변경하여 // 푸리에변환에 의한 주파수 영역의 원점을 중심으로 이동시키기 위함 ChangePosition(m_image_Re); cvMerge(m_image_Re, m_image_Im, NULL, NULL, m_pDFT_A); // m_pDFT_A에 대해 푸리에 변환을 수행 cvDFT(m_pDFT_A, m_pDFT_A, CV_DXT_FORWARD); // 이상적 저주파 통과 필터링 실행 if(m_low_Pass_Filtering == "ideal" && m_high_Pass_Filtering == "none") { IdealLowPassFiltering(m_pDFT_A, m_cutoff_Frequency); } // 버터워스 저주파 통과 필터링 실행 else if(m_low_Pass_Filtering == "butterworth" && m_high_Pass_Filtering == "none") { ButterworthLowPassFiltering(m_pDFT_A, m_cutoff_Frequency, 2); } // 가우시안 저주파 통과 필터링 실행 else if(m_low_Pass_Filtering == "gaussian" && m_high_Pass_Filtering == "none") { GaussianLowPassFiltering(m_pDFT_A, m_cutoff_Frequency); } // 이상적 고주파 통과 필터링 실행 else if(m_high_Pass_Filtering == "ideal" && m_low_Pass_Filtering == "none") { IdealHighPassFiltering(m_pDFT_A, m_cutoff_Frequency); } // 버터워스 고주파 통과 필터링 실행 else if(m_high_Pass_Filtering == "butterworth" && m_low_Pass_Filtering == "none") { ButterworthHighPassFiltering(m_pDFT_A, m_cutoff_Frequency, 2); } // 가우시안 고주파 통과 필터링 실행 else if(m_high_Pass_Filtering == "gaussian" && m_low_Pass_Filtering == "none") { GaussianHighpassFiltering(m_pDFT_A, m_cutoff_Frequency); } else { //none } // 퓨리에 역변환 실행 cvDFT(m_pDFT_A, m_pDFT_A, CV_DXT_INV_SCALE); // 다중 채널의 행렬을 단일 채널 행렬로 분할(Re, Im으로) cvSplit(m_pDFT_A, m_image_Re, m_image_Im, NULL, NULL); // 저주파일때만 실행 if((m_low_Pass_Filtering == "ideal" || m_low_Pass_Filtering == "butterworth" || m_low_Pass_Filtering == "gaussian") && m_high_Pass_Filtering == "none") { ChangePosition(m_image_Re); cvScale(m_image_Re, m_result_img, 1); } // 고주파일때만 실행 if((m_high_Pass_Filtering == "ideal" || m_high_Pass_Filtering == "butterworth" || m_high_Pass_Filtering == "gaussian") && m_low_Pass_Filtering == "none") { // 스펙트럼의 진폭을 계산 Mag=sqrt(Re^2 + Im^2) cvPow(m_image_Re, m_image_Re, 2.0); cvPow(m_image_Im, m_image_Im, 2.0); cvAdd(m_image_Re, m_image_Re, m_image_Re); cvPow(m_image_Re, m_image_Re, 0.5); // 진폭 화상의 픽셀치가 min과 max사이에 분포하로독 스케일링 double min_val, max_val; cvMinMaxLoc(m_image_Re, &min_val, &max_val, NULL, NULL); cvScale(m_image_Re, m_result_img, 255.0/max_val); } // 1채널 영상의 3채널 영상으로의 변환 cvMerge(m_result_img, m_result_img, m_result_img, NULL, m_final_img); // 아웃풋 push // RawImage의 이미지 포인터 변수 할당 RawImageData *pimage = result.getImage(); // 입력된 이미지 사이즈 및 채널수로 로 재 설정 pimage->resize(m_final_img->width, m_final_img->height, m_final_img->nChannels); // 영상의 총 크기(pixels수) 취득 int size = m_final_img->width * m_final_img->height * m_final_img->nChannels; // 영상 데이터로부터 영상값만을 할당하기 위한 변수 unsigned char *ptrdata = pimage->getData(); // 현재 프레임 영상을 사이즈 만큼 memcpy memcpy(ptrdata, m_final_img->imageData, size); // 포트아웃 opros_any mdata = result; ImageOut.push(result);//전달 delete pData; } else { // 아웃풋 push // 아웃풋 push // RawImage의 이미지 포인터 변수 할당 RawImageData *pimage = result.getImage(); // 입력된 이미지 사이즈 및 채널수로 로 재 설정 pimage->resize(m_orig_img->width, m_orig_img->height, m_orig_img->nChannels); // 영상의 총 크기(pixels수) 취득 int size = m_orig_img->width * m_orig_img->height * m_orig_img->nChannels; // 영상 데이터로부터 영상값만을 할당하기 위한 변수 unsigned char *ptrdata = pimage->getData(); // 현재 프레임 영상을 사이즈 만큼 memcpy memcpy(ptrdata, m_orig_img->imageData, size); // 포트아웃 opros_any mdata = result; ImageOut.push(result);//전달 delete pData; } } return OPROS_SUCCESS; }
ReturnType HumanDetection::onExecute() { // 영상을 Inport로부터 취득 opros_any *pData = ImageIn.pop(); RawImage result; std::vector<PositionDataType> data; if(pData != NULL){ // 포트로 부터 이미지 취득 RawImage Image = ImageIn.getContent(*pData); RawImageData *RawImage = Image.getImage(); // 현재영상의 크기를 취득 m_in_width = RawImage->getWidth(); m_in_height = RawImage->getHeight(); // 원본영상의 이미지영역 확보 if(m_orig_img == NULL){ m_orig_img = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 3); } if(m_result_img == NULL){ m_result_img = cvCreateImage(cvSize(m_in_width, m_in_height), IPL_DEPTH_8U, 3); } // 영상에 대한 정보를 확보!memcpy memcpy(m_orig_img->imageData, RawImage->getData(), RawImage->getSize()); m_img_mat = Mat(m_orig_img); vector<Rect> found, found_filtered; m_hog.detectMultiScale(m_img_mat, found, 0, Size(8,8), Size(32,32), 1.05, 2); int i, j; // 사이즈의 검출 for(i = 0; i < found.size(); i++){ Rect r = found[i]; for(j = 0; j < found.size(); j++){ if(j != i && (r & found[i]) == r){ break; } } if(j == found.size()){ found_filtered.push_back(r); } } outPoint.x = 0; outPoint.y = 0; rect_width = 0; rect_height = 0; // 사람 검출에대한 위치지정 for(i = 0; i < found_filtered.size(); i++){ Rect r = found_filtered[i]; r.x += cvRound(r.width*0.1); r.width = cvRound(r.width*0.8); r.y += cvRound(r.height*0.07); r.height = cvRound(r.height*0.8); rectangle(m_img_mat, r.tl(), r.br(), cv::Scalar(0, 255, 0), 3); //사각형 시작점 보존 outPoint.x = r.tl().x; outPoint.y = r.tl().y; rect_width = r.br().x - r.tl().x; rect_height = r.br().y - r.tl().y; } // 위치 정보 출력 if(outPoint.x != 0 && outPoint.y !=0) { PositionDataType base; base.setName(""); base.setX(outPoint.x); base.setY(outPoint.y); base.setHeight(rect_height); base.setWidth(rect_width); base.setRadian(NULL); data.push_back(base); PositionDataOut.push(data); } m_result_img = &IplImage(m_img_mat); // RawImage의 이미지 포인터 변수 할당 RawImageData *pimage = result.getImage(); // 입력된 이미지 사이즈 및 채널수로 로 재 설정 pimage->resize(m_result_img->width, m_result_img->height, m_result_img->nChannels); // 영상의 총 크기(pixels수) 취득 int size = m_result_img->width * m_result_img->height * m_result_img->nChannels; // 영상 데이터로부터 영상값만을 할당하기 위한 변수 unsigned char *ptrdata = pimage->getData(); // 현재 프레임 영상을 사이즈 만큼 memcpy memcpy(ptrdata, m_result_img->imageData, size); // 포트아웃 opros_any mdata = result; ImageOut.push(result);//전달 delete pData; } return OPROS_SUCCESS; }