영상 캡쳐하는 프로그래밍 질문입니다
글쓴이: curajc / 작성시간: 화, 2005/09/27 - 8:25오후
로지텍 퀵캠으로 영상처리를 하고 있는 학생입니다.
이미지 캡쳐하고 window하나 만들어서 보여주는 프로그램인데
return_value = ioctl(fd, VIDIOCSPICT, &pic);
if ( return_value < 0 )
{
fprintf(stderr,"Failed to set the image properties\n");
exit(1);
}
이 부분에서 자꾸 오류가 나면서 창이 그냥 닫힙니다. ㅠㅠ
(VIDIOCGPICT로 미리 pic도 얻었습니다)
나름대로 요것조것 해본결과 palette부분 설정이 바뀌지 않는것 같은데...
혹시해서 원래 설정대로 palette =VIDEO_PALETTE_YUV420P
로 하면 이 오류는 나지 않는데, 대신에
XIO: fatal IO error 14(Bad address) on X server ":0.0"
after 13 requests (6 known processed) with 0 events rremaining.
이라는 메시지가 나면서 창이 그냥 닫힙니다.
설마 x-window에서는 yuv포맷으론 display가 안되나요??
영상 처리 첨이라 힘드네요ㅠㅠ 도와주세요~~~
소스 첨부 합니다-------------------------
#include <X11/Xlib.h> #include <unistd.h> #include <stdio.h> #include <linux/videodev.h> #include <fcntl.h> #include <sys/mman.h> #include <sys/ioctl.h> char *v4l_init(); char *v4l_capture(); int fd; unsigned char *map; struct video_mmap v_map; struct video_mbuf m_buf; int main( int argc, char * argv[] ) { Display *display; Window window; GC gc; Visual *visual; XImage *display_image; unsigned char *buffer; int window_width,window_height; display = XOpenDisplay("localhost:0.0"); /* window size 768*480 */ window_width = 768; window_height = 480; window = XCreateSimpleWindow(display, RootWindow(display,0), 50, 50, window_width, window_height, 3, BlackPixel(display,0), WhitePixel(display,0)); gc = XCreateGC(display, window, 0L, (XGCValues *) NULL); XMapWindow(display, window); XFlush(display); buffer = v4l_init(); /* video capture device initialize */ while ( 1 ) { buffer = v4l_capture(); /* video capture */ /* * image create - depth = default(window depth) * size = 768 * 480 * RGB color 32bit (blue, green, red, alpha) */ display_image = XCreateImage(display, DefaultVisual(display, 0), DefaultDepth(display, 0), ZPixmap, 0, buffer, 768, 480, 32, 0); display_image->byte_order = LSBFirst; /* display image */ XPutImage(display, window, gc, display_image, 0, 0, 0, 0, 768, 480); } return 0; } char *v4l_init() { int width, height; int depth, palette; int return_value; char *device; struct video_capability cap; struct video_channel chan; struct video_window win; struct video_picture pic; /* capture device is video0 */ device = "/dev/video0"; if ( (fd = open(device, O_RDONLY)) < 0 ) { fprintf(stderr, "video device %s could not be opened\n", device); exit(1); } return_value = ioctl(fd , VIDIOCGCAP, &cap); if ( return_value < 0 ) { fprintf(stderr, "ioctl on VIDIOCGCAP failled\n"); exit(1); } /* capture channel is 0 */ chan.channel = 0; // chan.flags = 0; chan.type = VIDEO_TYPE_CAMERA; chan.norm = VIDEO_MODE_NTSC; return_value = ioctl(fd, VIDIOCSCHAN, &chan); if ( return_value < 0 ) { fprintf(stderr, "ioctl on VIDIOCSCHAN failed\n"); exit(1); } return_value = ioctl(fd, VIDIOCGWIN, &win); /* capture image depth is 32 and palette is rgb32 */ depth = 32; palette = VIDEO_PALETTE_RGB32; width = win.width = cap.maxwidth; height = win.height = cap.maxheight; win.x = win.y = win.chromakey = win.flags = 0; return_value = ioctl(fd, VIDIOCSWIN, &win); if ( return_value < 0 ) { fprintf(stderr,"ioctl on VIDIOCSWIN failed\n"); exit(1); } return_value = ioctl(fd, VIDIOCGPICT, &pic); if ( return_value < 0 ) { fprintf(stderr,"Failed to get the image properties\n"); exit(1); } printf("depth = %d\n", pic.depth); if(pic.palette == VIDEO_PALETTE_YUV420P) printf("2\n"); // printf("palette = %d\n", pic.palette); pic.depth = depth; pic.palette = palette; return_value = ioctl(fd, VIDIOCSPICT, &pic); if ( return_value < 0 ) { fprintf(stderr,"Failed to set the image properties\n"); exit(1); } return_value = ioctl(fd, VIDIOCGMBUF, &m_buf); if ( return_value < 0 ) { fprintf(stderr, "Failed to get information of capture memory space.\n"); exit(1); } map = (char*) mmap(0, m_buf.size, PROT_READ, MAP_SHARED, fd, 0); if ( map == MAP_FAILED ) { fprintf(stderr,"Failed to get pointer to memory mapped area.\n"); exit(1); } v_map.height = height; v_map.width = width; v_map.format = palette; /* 4 frame use */ v_map.frame = 0; return_value = ioctl(fd, VIDIOCMCAPTURE, &v_map); v_map.frame = 1; return_value = ioctl(fd, VIDIOCMCAPTURE, &v_map); v_map.frame = 2; return_value = ioctl(fd, VIDIOCMCAPTURE, &v_map); v_map.frame = 3; return_value = ioctl(fd, VIDIOCMCAPTURE, &v_map); return map; } char *v4l_capture() { /* capture frame with 4 frame buffer */ ioctl(fd, VIDIOCSYNC, &v_map); v_map.frame++; if ( v_map.frame == 4 ) v_map.frame = 0; ioctl(fd, VIDIOCMCAPTURE, &v_map); return map+m_buf.offsets[v_map.frame]; }
Forums:
Re: 영상 캡쳐하는 프로그래밍 질문입니다
저도 이번에 프레임그래버로, 캡쳐해서 화면뿌려주는 프로그램을 했었습니다. Qt쓰레드는 캡쳐받는 무한루프로 돌려서, 캡쳐후 GUI로 이미지 주는 방식을 택했습니다.
받아 올려고 하는 이미지 타입이 적절하지 못하기 때문에,
생기는 현상이라 생각됩니다. 이미지 크기를 말도안되게
크게 해보니, 위와같은 에러가 생기더라고요.
저도 님의 생각에 동의 합니다. yuv 포멧을 바로 Xwindow 에 쓸수 없을거 같습니다. xwindow 에 맞도록 바꾸는 부분을 본 기억이 있습니다. 아니면 캡쳐해서 바로 뿌리지 마시고, 한 장 정도만 캡쳐해서 파일 출력을 해보시는 것도 한가지 방법이 되지 않을까요?
저는 pci 카드에서 받아오게 되어서, 바로 ppm 파일을 사용했었습니다.
님의 가려운 곳을 긁어주지는 못하겠는데, 참고하시라는
생각에 덧 글 달아봅니다. 행운을 빌겠습니다.
"마무리가 반이다" -- woox
ppm파일은 어떻게??
어디에 저장이 되는 건가요???
포맷을 바꾸는 것은 찾았는데.....ppm파일을 xwindow에서 보는것은 어찌해야 좋을지 모르겠습니다. ;;;;;;;;;;;;;
일단 YUV 포멧은 논외로 하시고...
저는 YUV 포멧으로 받아서 Xwindow에 쓴것은 아니기 때문에, 그 부분은 논외로 하시고.
ppm 파일 종류가 두(?)가지 일겁니다.
p3, p6 이렇게요.
각 파일을 에디터로 열어보시면, 헤더에
이렇게 되어있으면 P6 입니다. P3는 당연히 P6 대신 P3가 되어있겠죠. 두 파일의 차이점은 P3는 640,480 크기의 파레트 의 한 점에 대하여 각각 RGB 값으로 표현되어 있습니다. 즉, 아스키 값이죠. 그러나, P6는 바이너리 포멧입니다.
그러면, Sync까지 끝낸 상황이라고 가정하면 ,
P3 포멧으로 PPM 파일을 만들어 내려면,
파일을 열어보시면 아스키 값이 저장됩니다. 메모리에는 BGR 형태로 저장되어있으므로, 파일 출력시에 RGB로바꾸어서 저장시킵니다.
그리고 P6의 경우의 함수는 메모리의 내용을 그대로 쓰면됩니다.
파일이 생성되면
xview p3out.ppm or xview p6out.ppm 혹은 gqview로 보시면, 됩니다.
이상은 제 경험이고요. USB카메라는 캡처시 팰레트를 YUV 이던데, 이 부분은 다른 경험있으신 분들이 답글 달아 주지 않겠나 합니다.
감사합니다~
아직 화면으로 보진 못했지만ㅠㅠ
알려주신 방법대로 해보았는데, xview는 ppm파일을 지원하지 않
더라구여;;;
어쨌든 ppm으로 변환하여 저장되는 것까진 확인했습니다~~
감사합니다~~*
댓글 달기