DarkNet 시리즈 - Image Opencv
image_opencv
image_to_ipl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifdef OPENCV
using namespace cv;
extern "C" {
IplImage *image_to_ipl(image im)
{
int x,y,c;
IplImage *disp = cvCreateImage(cvSize(im.w,im.h), IPL_DEPTH_8U, im.c);
int step = disp->widthStep;
for(y = 0; y < im.h; ++y){
for(x = 0; x < im.w; ++x){
for(c= 0; c < im.c; ++c){
float val = im.data[c*im.h*im.w + y*im.w + x];
disp->imageData[y*step + x*im.c + c] = (unsigned char)(val*255);
}
}
}
return disp;
}
함수 이름: image_to_ipl
입력:
- image im (이미지 구조체)
동작:
- 입력으로 들어온 이미지 구조체를 OpenCV의 IplImage 구조체로 변환하여 반환합니다.
- 변환 과정에서는 이미지 데이터의 크기 및 채널에 맞게 IplImage 구조체를 생성한 뒤, 입력 이미지 데이터를 0~255 범위로 스케일링하여 IplImage에 저장합니다.
설명:
- YOLO같은 딥러닝 모델에서는 이미지를 다루어야 하기 때문에, 이러한 이미지를 각 프레임마다 OpenCV의 IplImage 구조체로 변환하여 출력하기 위한 함수입니다.
- IplImage 구조체는 OpenCV에서 이미지를 다루기 위해 사용되는 구조체로, 채널, 크기, 데이터 타입 등 이미지 정보를 담고 있습니다.
- 이 함수에서는 입력으로 들어온 이미지 구조체를 IplImage 구조체로 변환하여 반환합니다.
ipl_to_image
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
image ipl_to_image(IplImage* src)
{
int h = src->height;
int w = src->width;
int c = src->nChannels;
image im = make_image(w, h, c);
unsigned char *data = (unsigned char *)src->imageData;
int step = src->widthStep;
int i, j, k;
for(i = 0; i < h; ++i){
for(k= 0; k < c; ++k){
for(j = 0; j < w; ++j){
im.data[k*w*h + i*w + j] = data[i*step + j*c + k]/255.;
}
}
}
return im;
}
함수 이름: ipl_to_image
입력:
- IplImage* src (IplImage 포인터)
동작:
- OpenCV 라이브러리의 IplImage 포맷으로 저장된 이미지를 Darknet의 image 포맷으로 변환한다.
- 주어진 IplImage 포인터로부터 이미지의 높이, 너비, 채널 수를 가져와서 이를 기반으로 새로운 image를 만든다.
- 그리고 나서 IplImage의 imageData 포인터를 이용하여 이미지 데이터를 가져와서 새로 만든 image의 데이터 포인터에 할당한다.
설명:
- OpenCV의 IplImage 포맷으로 저장된 이미지를 Darknet의 image 포맷으로 변환하는 함수이다.
- 주어진 IplImage 포인터로부터 이미지의 높이, 너비, 채널 수를 가져온다.
- 가져온 높이, 너비, 채널 수를 이용하여 make_image 함수를 호출하여 새로운 image를 만든다.
- 이후, IplImage의 imageData 포인터를 이용하여 이미지 데이터를 가져와서 새로 만든 image의 데이터 포인터에 할당한다.
- 이미지 데이터의 픽셀 값 범위가 0
255이므로, 255로 나누어서 01 범위로 정규화한다. 반환값: 변환된 image 구조체
image_to_mat
1
2
3
4
5
6
7
8
9
10
11
12
Mat image_to_mat(image im)
{
image copy = copy_image(im);
constrain_image(copy);
if(im.c == 3) rgbgr_image(copy);
IplImage *ipl = image_to_ipl(copy);
Mat m = cvarrToMat(ipl, true);
cvReleaseImage(&ipl);
free_image(copy);
return m;
}
함수 이름: image_to_mat
입력:
- image im (입력 이미지)
동작:
- 입력 이미지를 OpenCV의 Mat 형식으로 변환합니다.
- 먼저 입력 이미지를 복사하고 제약 조건을 적용한 후, 입력 이미지가 3채널(RGB)인 경우 rgbgr 변환을 수행합니다.
- 그 후, 변환된 이미지를 IplImage 형식으로 변환하고 cvarrToMat 함수를 사용하여 Mat 형식으로 변환합니다. 마지막으로 IplImage 메모리를 해제하고 이미지 복사본을 해제합니다.
설명:
- copy_image(im): 입력 이미지의 복사본을 생성합니다.
- constrain_image(copy): 이미지를 0~1 값으로 제한합니다.
- rgbgr_image(copy): 이미지 색상 채널을 RGB에서 BGR 순으로 변경합니다.
- image_to_ipl(copy): 이미지를 IplImage 형식으로 변환합니다.
- cvarrToMat(ipl, true): IplImage를 Mat 형식으로 변환합니다.
- cvReleaseImage(\&ipl): IplImage 메모리를 해제합니다.
- free_image(copy): 이미지 복사본 메모리를 해제합니다.
mat_to_image
1
2
3
4
5
6
7
image mat_to_image(Mat m)
{
IplImage ipl = m;
image im = ipl_to_image(&ipl);
rgbgr_image(im);
return im;
}
함수 이름: mat_to_image
입력:
- Mat m (OpenCV에서 제공하는 이미지 포맷 Mat 형식의 이미지)
동작:
- OpenCV의 Mat 형식의 이미지를 Darknet의 image 형식으로 변환하는 함수입니다.
- 먼저, Mat 형식의 이미지를 IplImage 형식으로 변환한 후 ipl_to_image 함수를 사용하여 Darknet의 image 형식으로 변환합니다.
- 이후, rgbgr_image 함수를 사용하여 이미지의 색상을 변환합니다.
설명:
- 입력으로 받은 Mat 형식의 이미지를 Darknet의 image 형식으로 변환하여 반환하는 함수입니다.
open_video_stream
1
2
3
4
5
6
7
8
9
10
11
void *open_video_stream(const char *f, int c, int w, int h, int fps)
{
VideoCapture *cap;
if(f) cap = new VideoCapture(f);
else cap = new VideoCapture(c);
if(!cap->isOpened()) return 0;
if(w) cap->set(CV_CAP_PROP_FRAME_WIDTH, w);
if(h) cap->set(CV_CAP_PROP_FRAME_HEIGHT, w);
if(fps) cap->set(CV_CAP_PROP_FPS, w);
return (void *) cap;
}
함수 이름: open_video_stream
입력:
- const char *f: 비디오 파일의 경로 (비디오 스트림이 아닌 경우 0으로 설정)
- int c: 비디오 캡처 장치의 인덱스 (비디오 파일이 아닌 경우 0으로 설정)
- int w: 비디오 프레임의 너비 (설정하지 않은 경우 0)
- int h: 비디오 프레임의 높이 (설정하지 않은 경우 0)
- int fps: 비디오의 초당 프레임 수 (설정하지 않은 경우 0)
동작:
- 입력으로 주어진 비디오 파일 또는 캡처 장치에서 비디오 스트림을 열고, 비디오 스트림을 캡처하는 데 사용되는 VideoCapture 객체를 생성한다.
- VideoCapture 객체가 정상적으로 열리지 않은 경우 0을 반환한다.
- 너비, 높이 및 FPS 값이 설정되었다면, 해당 값을 VideoCapture 객체에 설정한다.
- VideoCapture 객체의 포인터를 반환한다.
설명:
- 입력된 비디오 파일 경로나 카메라 장치 번호에 해당하는 비디오 스트림을 열고, 프레임의 너비, 높이, 속도를 설정한다.
- 이때, 프레임 너비와 높이, 속도가 0이면 기본값으로 설정된다. 반환되는 VideoCapture 객체는 이후 비디오 프레임을 읽어오기 위해 사용된다.
get_image_from_stream
1
2
3
4
5
6
7
8
image get_image_from_stream(void *p)
{
VideoCapture *cap = (VideoCapture *)p;
Mat m;
*cap >> m;
if(m.empty()) return make_empty_image(0,0,0);
return mat_to_image(m);
}
함수 이름: get_image_from_stream
입력:
- void 포인터 p (영상 스트림 객체)
동작:
- 입력으로 받은 영상 스트림 객체에서 현재 프레임을 읽어와 OpenCV의 Mat 형식으로 저장하고, 이를 Darknet의 image 형식으로 변환하여 반환한다.
- 만약 현재 프레임이 없는 경우, 크기가 0인 빈 image를 반환한다.
설명:
- VideoCapture: OpenCV에서 영상 스트림을 처리하기 위한 클래스
- Mat: OpenCV에서 이미지를 처리하기 위한 클래스
- make_empty_image(w,h,c): Darknet에서 빈 image를 생성하는 함수 (너비 w, 높이 h, 채널 수 c)
- mat_to_image(m): OpenCV의 Mat 형식의 이미지를 Darknet의 image 형식으로 변환하는 함수
load_image_cv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
image load_image_cv(char *filename, int channels)
{
int flag = -1;
if (channels == 0) flag = -1;
else if (channels == 1) flag = 0;
else if (channels == 3) flag = 1;
else {
fprintf(stderr, "OpenCV can't force load with %d channels\n", channels);
}
Mat m;
m = imread(filename, flag);
if(!m.data){
fprintf(stderr, "Cannot load image \"%s\"\n", filename);
char buff[256];
sprintf(buff, "echo %s >> bad.list", filename);
system(buff);
return make_image(10,10,3);
//exit(0);
}
image im = mat_to_image(m);
return im;
}
함수 이름: load_image_cv
입력:
- filename (char *) : 이미지 파일 이름
- channels (int) : 채널 수 (0, 1, 3 중 하나)
동작:
- OpenCV를 사용하여 이미지 파일을 로드하고, 채널 수를 지정할 수 있음.
- 이미지를 Mat 형식으로 읽은 다음, mat_to_image() 함수를 사용하여 image 형식으로 변환하여 반환함.
설명:
- OpenCV를 사용하여 이미지 파일을 읽어옴
- channels 값에 따라 이미지를 grayscale 또는 color 이미지로 읽어옴 (channels=0인 경우 grayscale, channels=1인 경우 color, channels=3인 경우 RGB 이미지를 읽어옴)
- 이미지 파일이 없을 경우, 콘솔에 에러 메시지를 출력하고, 크기가 10x10이고 채널 수가 3인 빈 이미지를 생성하여 반환함.
- mat_to_image() 함수를 사용하여 Mat 형식의 이미지를 image 형식으로 변환하여 반환함.
show_image_cv
1
2
3
4
5
6
7
8
int show_image_cv(image im, const char* name, int ms)
{
Mat m = image_to_mat(im);
imshow(name, m);
int c = waitKey(ms);
if (c != -1) c = c%256;
return c;
}
함수 이름: show_image_cv
입력:
- image im (표시할 이미지)
- const char* name (윈도우 창 이름)
- int ms (윈도우가 열린 상태로 유지할 시간)
동작:
- 입력으로 받은 이미지를 OpenCV Mat 형식으로 변환하고, 해당 이미지를 윈도우 창에 표시한다.
- 그리고 윈도우가 열린 상태로 ms (입력으로 받은 시간) 밀리초만큼 대기한 후, 키보드 입력이 있으면 해당 입력의 아스키 코드 값을 반환하고, 그렇지 않으면 -1을 반환한다.
설명:
- Darknet에서 표시할 이미지를 OpenCV의 imshow 함수를 사용하여 윈도우 창에 표시하는 함수이다.
- 이미지를 OpenCV의 Mat 형식으로 변환하여 imshow 함수에 전달하고, 입력된 시간(ms)만큼 대기하다가 키보드 입력이 있으면 해당 입력의 아스키 코드 값을 반환한다.
- 반환된 값이 -1이면 아무 입력도 없었다는 뜻이다.
make_window
1
2
3
4
5
6
7
8
9
10
11
12
void make_window(char *name, int w, int h, int fullscreen)
{
namedWindow(name, WINDOW_NORMAL);
if (fullscreen) {
setWindowProperty(name, CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);
} else {
resizeWindow(name, w, h);
if(strcmp(name, "Demo") == 0) moveWindow(name, 0, 0);
}
}
}
함수 이름: make_window
입력:
- name (char*): 창의 이름
- w(int): 창의 너비
- h(int): 창의 높이
- fullscreen(int): 전체화면 여부(0 또는 1)
동작:
- OpenCV 라이브러리의 namedWindow() 함수를 사용하여 이름이 name인 창을 생성한다.
- fullscreen이 1인 경우 창을 전체화면으로 표시하고, 0인 경우 창의 크기를 w x h로 조정한다.
- Demo라는 이름의 창인 경우, (0,0) 위치로 이동시킨다.
설명:
- OpenCV를 사용하여 이미지를 보여주는 창을 만드는 함수이다.
- 창의 이름과 크기, 전체화면 여부를 입력으로 받고, namedWindow()과 setWindowProperty() 또는 resizeWindow()와 moveWindow() 함수를 사용하여 창을 생성하거나 크기와 위치를 조정한다.
This post is licensed under CC BY 4.0 by the author.