11장 <동영상 처리> 과제
과제1. 카메라로부터 들어오는 컬러영상에서 손(hand)영역을 검출하여 검정색으로 표시하고 손영역의 무게중심을 구하여 영상의 우측상단에 출력하고 중심점에 빨간색원을 그려주는 프로그램을 작성하시오. 또한, 명령창에도 중심의 좌표를 실시간으로 출력하라.
#include<cv.h>
#include <highgui.h>
#include<stdio.h>
//void on_mouseEvent(int event, int x, int y, int flags, void* param);
int main()
{
IplImage *frame; // 원본영상
IplImage *dst; // 색 검출 영상
int width, height; // 창의 가로, 세로
int i, j, index;//반복문 첨자
unsigned char R, G, B;//각 채널에 해당하는 인덱스
int nCount; //피부색으로 검출된 픽셀의 갯수
int DrawX, DrawY; //피부색으로 검출된 픽셀의 각 좌표 합 x,y
CvFont font;//폰트 정보를 담고 있는 구조체 변수선언.
char str[20];//중심좌표를 문자열로 저장할 char형 배열변수 선언
CvCapture* capture = cvCaptureFromCAM(0); //캠으로부터 동영상 정보 가져와서 시작주소 저장, 동적할당
int fps = 30; //fps값 설정
frame = cvQueryFrame(capture); //동영상으로부터 프레임 잡고, IplImage구조체로 변환후 저장.
width = frame->width; // frame으로부터 width와 height 정보 저장
height = frame->height;
cvNamedWindow("Original", CV_WINDOW_AUTOSIZE); //윈도우 생성을 위한 메모리 동적할당
cvNamedWindow("Hand Tracking", CV_WINDOW_AUTOSIZE);//윈도우 생성을 위한 메모리 동적할당
// frame와 같은 크기를 갖는 3채널 영상 생성
dst = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 3); //크기,채널,깊이 정보 받아서 결과영상을 저장할 메모리 동적 할당
while (capture) {//정상작동시 (에러x) 무한루프
nCount = 0;//0으로 초기화-->에러처리
DrawX = 0;//초기값 0, 매 프레임마다 0으로 초기화시켜서 값이 누적되지 않도록 한다
DrawY = 0;
frame = cvQueryFrame(capture); //캠의 동영상으로부터 프레임을 정지영상으로 받아오기(grab,retrieve 함수 합친함수)
for (i = 0; i < height; i++) { //행
for (j = 0; j < (frame->widthStep); j +=(frame->nChannels)) { //열 //3채널이므로 3씩 건너뛴다
index = i * frame->widthStep + j; //채널3개니까 1차원배열 IplImage 구조체 형식 영상에서는 채널수 곱해줌
R = frame->imageData[index + 2]; // R영역
G = frame->imageData[index + 1]; // G영역
B = frame->imageData[index + 0]; // B영역
// 피부색으로 예상되는 범위 설정-->검정색으로 변경
if (R > 100 && R < 240 &&
G > 70 && G < 200 &&
B > 50 && B < 170) {
dst->imageData[index + 0] = 0; //피부색으로 검출된 픽셀값 검정으로 변경
dst->imageData[index + 1] = 0;
dst->imageData[index + 2] = 0;
nCount ++;//검출된 픽셀갯수 카운트
DrawX += j/3; //j값을 3채널씩 건너뛰었으므로 좌표값도 3으로 나눠준다
DrawY += i;
}
else {
// 원본영상 픽셀값 그대로 붙이기
dst->imageData[index + 0] = frame->imageData[index + 0];
dst->imageData[index + 1] = frame->imageData[index + 1];
dst->imageData[index + 2] = frame->imageData[index + 2];
}
}
}
if (nCount != 0) //검출된 픽셀 갯수가 1이상일때 실행
{
DrawX /= nCount; //무게중심 x좌표
DrawY /= nCount; //무게중심 y좌표
printf("(%d,%d)\n", DrawX, DrawY);//명령창에 출력
cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0.0, 1, 8); //폰트 구조체를 초기화한다
sprintf(str, "(%d,%d)", DrawX, DrawY); //숫자를 문자열로 버퍼에 저장함
cvPutText(dst, str, cvPoint(450, 50), &font, CV_RGB(0, 0, 0)); //버퍼에 저장된 문자열 영상의 무게중심에 출력
cvCircle(dst, cvPoint(DrawX, DrawY), 10, CV_RGB(0, 0, 255), 1, 8, 0); //무게중심 좌표에 파란색 원그리기
}
else //검출된 픽셀갯수가 0일 경우 에러처리 0/0 연산 방지
printf("해당 픽셀이 없습니다\n"); //에러메세지 출력
cvShowImage("Original", frame);//원본영상 프레임 출력
cvShowImage("Hand Tracking", dst);//결과 영상 프레임 출력
if (cvWaitKey(33) >= 0) break;//30fps,1000msec
}
cvReleaseCapture(&capture);//동적할당 메모리 해제
cvReleaseImage(&dst);//동적할당 메모리 해제
cvDestroyWindow("Original");//동적할당 메모리 해제
cvDestroyWindow("Hand Tracking");//동적할당 메모리 해제
return 0; //프로그램 종료
}
과제2. 카메라를 이용하여 찍은 영상을 화면에 표시하고 동영상으로 저장하시오. 사용자가 키보드를 누를때까지 저장하도록 하라.
#include<highgui.h>
int main()
{
IplImage* image = NULL; //영상 정보를 담을 구조체 변수 선언,초기화
CvCapture* capture = NULL; //동영상 정보를 담을 구조체 변수 선언, 초기화
CvVideoWriter* VideoOut = NULL; //비디오 저장함수를 사용하기 위한 자료형 변수선언
int fps = 30; //fps값 설정
cvNamedWindow("Camera", CV_WINDOW_AUTOSIZE); //윈도우 생성에 필요한 동적할당
capture = cvCaptureFromCAM(0); //CAM으로 동영상 불러온다.
while (1)
{
cvGrabFrame(capture);//프레임 잡음
image = cvRetrieveFrame(capture, 0);//잡은 압축된 프레임을 변환하여 이미지 구조체 변수에 저장
if (!VideoOut) VideoOut = cvCreateVideoWriter("CamSave.avi", -1, fps, cvGetSize(image), 1); //최초한번만 실행,초당프레임 30으로 설정.
cvShowImage("Camera", image); //프레임 출력
cvWriteFrame(VideoOut, image); //비디오 파일을 열 프레임을 쓴다. 출력할 때 사용
if (cvWaitKey(10) >= 0) break; //키입력 10msec 무한대기, 입력시 프로그램종료
}
cvReleaseVideoWriter(&VideoOut); //cvCreateVideoWriter함수에 의해 동적할당된 비디오 writer해제.
cvReleaseCapture(&capture); //cvRetrieveFrame함수에 의해 할당된 IplImage은 직접해제x,CvCapture해제하여 관련된 메모리 해제.
cvDestroyWindow("Camera"); //cvNamedWindow에 의해 동적할당된 메모리 해제
return 0;//프로그램 종료.
}
<유용한 함수> 과제
과제1. 사진에서 머리카락영역을 검출하여 빨간색으로 표시하고 영역의 무게중심을 구하여 영상에 원을 그리고 영상과 명령창에 무게중심의 좌표를 출력하는 프로그램을 작성하시오. 예제 4,5를 참조하라.
#include <highgui.h>
#include<stdio.h>
int main()
{
IplImage* src_image = NULL; //원본영상의 정보를 담은 구조체의 시작주소를 담을 포인터변수 선언,초기화
uchar *data; //픽셀값에 직접 접근하기 위한 포인터 변수 선언
int index, i, j; //반복문 첨자
int nCount; //검출된 픽셀의 갯수
int DrawX, DrawY; //검출된 픽셀의 x,y좌표 -->누적
CvFont font; //폰트 정보를 담는 구조체
char str[20]; //숫자를 문자열로 저장해둘 버퍼역할 배열변수선언
nCount = 0; //검출된 픽셀의 갯수 카운트 초기화
DrawX = 0;//검출된 픽셀의 x,y좌표 초기화
DrawY = 0;
src_image = cvLoadImage("image.jpg", -1); //파일로부터 영상 원본 그대로 로드
cvNamedWindow("Original", CV_WINDOW_AUTOSIZE); //윈도우 생성하기 위한 메모리 동적할당
cvNamedWindow("Result", CV_WINDOW_AUTOSIZE);
data = (uchar*)src_image->imageData; //원본영상의 픽셀값 직접접근하기 위해
cvShowImage("Original", src_image); //원본 이미지 출력
for (i = 0; i<src_image->height; i++) //행
for (j = 0; j<src_image->width; j++)//열
{
index = (i * src_image->width + j)*src_image->nChannels; //RGB 색상 인덱스값 저장-->BGR순서
if (data[index + 2] >30 && data[index + 2] <170 && //r
data[index + 1] > 10 && data[index + 1] <140 && //g
data[index + 0] > 10 && data[index + 0] <120) //b
{
data[index] = 0;
data[index + 1] = 0;
data[index + 2] = 255; //검출된 픽셀은 빨강으로 픽셀값 변경
nCount++; //검출된 픽셀수 카운트
DrawX +=j; //검출된 픽셀의 X,Y 좌표값 누적 합
DrawY +=i;
}
}
if (nCount != 0) // 0/0 에러방지 코드
{
DrawX /= nCount; //무게중심 좌표값 구함
DrawY /= nCount;
printf("(%d,%d)\n", DrawX, DrawY); //무게중심 좌표값 명령창에 출력
cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.4, 0.4, 0.0, 1, 8); //폰트 구조체 정보 초기화
sprintf(str, "(%d,%d)", DrawX, DrawY); //str에 출력할 문자열 저장
cvPutText(src_image, str, cvPoint(200, 50), &font, CV_RGB(0, 0, 0)); //폰트 정보 받아서 문자열 출력
cvCircle(src_image, cvPoint(DrawX, DrawY), 10, CV_RGB(0, 0, 0), 1, 8, 0); //무게중심 좌표에 검정색 원 그린다
}
else // 0/0 에러메세지 출력
printf("해당 픽셀을 찾을 수 없습니다\n");
cvShowImage("Result", src_image); //검출된 이미지 출력
cvWaitKey(0); //키보드입력 무한대기
cvDestroyWindow("Original"); //동적할당된 메모리 반환
cvDestroyWindow("Result");
cvReleaseImage(&src_image);
return 0; //프로그램 종료
}
'programming > Image Processing' 카테고리의 다른 글
OpenCV로 배우는 영상처리 및 응용:: 1장 (0) | 2020.06.25 |
---|---|
opencv 4.3.0 프로젝트 설정 (0) | 2020.05.12 |
OpenCV 최종과제 (0) | 2020.03.29 |
OpenCV를 이용한 영상처리::4~6장 과제 (0) | 2020.03.29 |
OpenCV를 이용한 영상처리::1~3장 과제 (0) | 2020.03.29 |