반응형


웹캠으로부터 캡처된 영상에 일련번호를 붙여서 이미지 파일로 저장하는 예제입니다.



sprintf 함수를 사용하여 img_000000.jpg ~ img_999999.jpg 까지 이미지 파일 이름을 생성하는 방법을 사용하였습니다.


더 많은 이미지 파일을 저장하려면 %6d 부분을 수정하면 됩니다.


sprintf( buf, "img_%06d.jpg", index);



img_999999.jpg까지 저장하면 다시 img_000000.jpg 파일 이름으로 저장하도록 작성되었습니다.




실행결과 저장된 이미지파일들입니다.





사용한 코드는 다음과 같습니다.


#include <opencv2/opencv.hpp>
#include <iostream>  

using namespace cv;
using namespace std;



int main(int, char**)
{
int index = 0;
char buf[256];
Mat frameMat;


VideoCapture videoCapture(0);
if (!videoCapture.isOpened())
{
printf("첫번째 카메라를 열수 없습니다. \n");
}


namedWindow("웹캠 영상", WINDOW_AUTOSIZE);


while(1)
{

//웹캡으로부터 한 프레임을 읽어옴  
videoCapture.read(frameMat);

//화면에 보여줌
imshow("웹캠 영상", frameMat);

//이미지로 저장  
sprintf(buf, "c:/temp/img_%06d.jpg", index);
cout << buf << endl;
imwrite(buf, frameMat);

index++;
if (index == 999999) index = 0;

if (waitKey(25) == 27) break; //ESC키 누르면 종료  
}


return 0;
}




일련번호를 붙여서 저장한 이미지들을 다시 동영상처럼 보이게 하고 싶으면 아래 코드를 사용하면 됩니다.


#include <opencv2/opencv.hpp>
#include <iostream>  

using namespace cv;
using namespace std;



int main(int, char**)
{
int index = 0;
char buf[256];
Mat frameMat;


namedWindow("이미지 영상", WINDOW_AUTOSIZE);

while(1)
{

//이미지로 저장  
sprintf(buf, "c:/temp/img_%06d.jpg", index);
cout << buf << endl;


frameMat = imread(buf, IMREAD_COLOR);
if (frameMat.empty()) {

index = 0;
}
else {

imshow("이미지 영상", frameMat);
index++;
}


if (waitKey(25) == 27) break; //ESC키 누르면 종료  
}


return 0;
}




앞에서 생성한 이미지파일들에서 하나라도 삭제되지 않은 상태로 실행시킨다고 가정하고 있습니다.


buf에 저장된 이미지 파일을 읽어올 수 없다면 마지막 일련번호 파일을 모두 읽은 것으로 간주하고 index를 다시 0으로 설정합니다.


결과적으로 일련번호 순서대로 이미지 파일을 읽어와서 반복적으로 화면에 보여주게 됩니다.


frameMat = imread(buf, IMREAD_COLOR);
if (frameMat.empty()) {

index = 0;
}
else {

imshow("이미지 영상", frameMat);
index++;
}



반응형

포스트 작성시에는 문제 없었지만 이후 문제가 생길 수 있습니다.
댓글로 알려주시면 빠른 시일내에 답변을 드리겠습니다.

여러분의 응원으로 좋은 컨텐츠가 만들어집니다.
지금 본 내용이 도움이 되었다면 유튜브 구독 부탁드립니다. 감사합니다 : )

유튜브 구독하기


제가 쓴 책도 한번 검토해보세요.

  1. 질문있습니다. 2017.04.04 01:45

    이미지 저장 경로를 바꾸는 방법과 그 저장된 이미지를 0부터 생성되고 있다면 동시에 0부터 지을 수 있는 방법이 있을까요 ..?? 계속 이미지가 쌓여서 ㅠㅠ

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2017.04.04 17:04 신고

      이미지 저장경로는 코드에서 다음 부분에 경로를 추가해주면 됩니다.
      "img_%06d.jpg"

      리눅스라면 이렇게 해주면 됩니다.
      "/home/webnautes/img_%06d.jpg"

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2017.04.04 17:05 신고

      원형큐를 구현하시면 해결될 듯합니다.

  2. 질문있습니다. 2017.04.04 02:58

    char[256]은 무슨뜻인가요 ?? ㅜㅠ 저는 문자 256개를 저장할 수있다고 보이는데 ...ㅠㅠ 이미지는 몇장까지 저장할 수 있는건가요 ..?? ㅜㅠㅠ

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2017.04.04 17:07 신고

      char buf[256]; 는 파일 이름을 저장하려고 추가한겁니다.

      아래처럼 버퍼에 파일이름을 입력합니다.
      sprintf( buf, "img_%06d.jpg",i );

      예제에서는 이미지 저장할 수 있는 갯수에 제한을 두지 않았습니다..

  3. 질문있습니다. 2018.12.20 11:31

    imwrite(buf, frameMat); 에서 아래와 같은 에러가 발생합니다. VS 2010 입니다.
    어떤 방법이 있을까요? 답변 부탁 드립다.. ㅜㅜ

    0x10310a14에 처리되지 않은 예외가 있습니다. 0xC0000005: 0x0c0de000 위치를 읽는 동안 액세스 위반이 발생했습니다.

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2018.12.20 11:38 신고

      혹시 이미지 저장시 경로에 포함된 디렉토리를 생성하셨나요?

  4. 질문있습니다. 2018.12.20 12:50

    빠른 답변 감사드립니다. ^^

    button 클릭 시 맨위의 code 그대로 copy 했습니다.
    temp 폴더에 img_000000.jpg 파일이 0KB로만 생성되고 액세스 위반 error가 뜹니다. ㅜㅜ

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2018.12.20 13:37 신고

      정확한 이유는 찾을수가 없네요.

      릴리즈모드로하고 이미지 파일 확장자를 bmp로 해서 진행해보세요

  5. 질문있습니다. 2018.12.20 15:37

    말씀해주신대로 이미지 파일 확장자를 bmp로 변경하니 잘 동작합니다;;;
    친절한 답변 진심으로 감사드립니다~~!!!

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2018.12.20 15:44 신고

      OpenCV에 포함되있는 jpg라이브러리가 문제 인가봅니다.

  6. 이런 경우는 어떤가요 2019.06.02 01:58

    실시간으로 영상이 촬영되고 있는 와중에 특정 이벤트에서만 이미지가 저장되게 합니다. 이미지가 저장되자마자 저장한 이미지를 불러오고 싶은데, 그러려면 다음 이미지 이름을 미리 알아야 하거나 이미지 네임부분을 계속 변화하게 해야할거 같습니다. 특정 이벤트가 발생했을 때만 이미지를 저장하고 그 이미지를 바로 불러오게하는 하나의 함수를 만들 방법이 없을까요? 영상은 계속 실행하는 중이라는 가정입니다.

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.06.02 12:49 신고

      이미지에 날짜와 시간을 붙여서 저장하면 어떨까 싶네요.

      그리고 불러오는 것은 영상이 저장된 디렉토리를 따로 생성하여 필요할때마다 해당 디렉토리의 파일 목록을 생성하여 하면 되지 않을까 싶네요.

  7. 이영우 2019.07.26 12:10

    웹캠 캡처 저장 시 화면에 초시계를 비춰 저장을 하면 같은 시간이 2번찍히고 그 다음 프레임에 두 프레임 이후 시간이 찍히는데 원인을 혹시 알고 계신가요?
    ex 30fps 기준 첫화면 0ms, 두번째화면 0ms, 세번째화면 70ms

  8. 감사합니다 2019.09.11 16:36

    항상 잘 보고있습니다. 구독눌렀습니다 ^^ 힘내세요~~ 감사합니다

  9. 감사합니다 2019.09.11 16:58

    제가 해보는중인데
    jpg, bmp, png 뭘 저장해도
    다시 출력할때 회색화면만뜹니다. 분명 이름도 똑같은거로 해줬는데 애초에 저장이 잘 안된거같아요
    제가 이미지 사진 보려고 클릭해봐도 불러올수가없다네요.

  10. 질문이있어요 2020.01.12 00:06

    이미지가 img_000000.jpg ~ img_999999.jpg 가 있는상황에서요 (비디오캡쳐 아니고 이미지가 먼저 존재하는상황)
    imread로 순차적으로 하나씩 이미지를 불러와서 threshold를 해주려고 하는데요 for문으로 999999까지 돌려서 하려고 합니다. 그런데 imread 인자가 경로,형식? 이다 보니 숫자인자를 어디에 써줘야 되는지 모르겠네요
    제가 막힌부분 ex)
    for (int i = 0; i < 999999; i++) {
    image = imread("C:\\lenna_%06d.PNG", IMREAD_COLOR); //여기서 i를 어디에 집어넣어줘야될지..
    if (image.empty()) {
    printf("aaa");
    }
    else { //else일 때 이진화 실행
    threshold(image, out, 127, 255, THRESH_BINARY);
    imwrite("C:\\lenna_%06d.PNG", out); //여기도 마찬가지 %d에 들어갈 i가 들어가지않아요 ㅠ

  11. 이길호 2020.02.07 00:52

    안녕하세요. 정말 많은 도움 받고 있습니다.
    업무에 적용해보려고 많은 소스들은 봐왔지만 지금처럼 알기 쉽게 설명해주신분이 안계셨는데 정말 감사합니다.

    다름이 아니라

    //이미지로 저장
    sprintf(buf, "c:/temp/img_%06d.jpg", index);
    cout << buf << endl;
    imwrite(buf, frameMat);

    구문에서 컴파일하게 되면

    1>------ 빌드 시작: 프로젝트: image_counter, 구성: Debug x64 ------
    1>IMAGE_COUNTER.cpp
    1>g:\opencv_example\image_counter\image_counter\image_counter.cpp(36): error C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
    1>c:\program files (x86)\windows kits\10\include\10.0.17763.0\ucrt\stdio.h(1774): note: 'sprintf' 선언을 참조하십시오.
    1>"image_counter.vcxproj" 프로젝트를 빌드했습니다. - 실패
    ========== 빌드: 성공 0, 실패 1, 최신 0, 생략 0 ==========
    이런 결과가 나오네요.

    근데 혹시나해서
    printf(buf, "c:/temp/img_%06d.jpg", index);
    cout << buf << endl;
    imwrite(buf, frameMat);
    이렇게 해봤더니 결과나 컴파일이 진행 되더라구요. 혹시 sprintf 라는 선언이 잘못된게 아닌가 하는생각이 듭니다ㅣ.

    printf 랑 sprintf 랑 무슨 차이인지 알려주실 수 있나요?

    printf 로 컴파일하면 실행은 되지만 디버그 에러가 뜨면서 경로상 이미지는 저장이 안되네요. 아마도 printf 때문인거 같은데요.

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.02.07 10:38 신고

      비주얼 스튜디오에서 프로젝트 생성시 SDL을 체크하면 sprintf대신에 sprintf_s를 쓰라는 메시지가 나옵니다. 프로젝트 생성시 SDL을 체크하지말고 다시 생성해보세요

  12. Favicon of https://beakgong.tistory.com BlogIcon 백공잉 2020.02.07 12:04 신고

    감사합니다. 프로젝트 생성시 SDL 옵션이 안보여서 당황했는데요. 2017버전부터인가? 안보인다고 하더군요. (인터넷 검색해보니...)
    그래서 알아본 결과 속성>C/C++>일반 에 SDL 검사라는 옵션이 있어서 그걸 아니오 라고 했더니 정상 실행 됩니다.

  13. 질문자 2020.03.31 17:16

    질문 있습니다.

    카메라와 pc를 usb로 연결하고, 카메라에서 출력되는 프레임을 순서대로 저장하는 코드를 아래와 같이 작성하였습니다.
    저장되는 이미지의 갯수가 실제 카메라의 프레임 레이트보다 많습니다.
    혹시 원인을 아신다면 답변 부탁 드립니다 ^^

    #include <Windows.h>
    #include <iostream>
    #include <string>

    #include "opencv2/opencv.hpp"
    #include "libCamCap.h"

    using namespace cv;
    using namespace std;

    #define MODEL_5CRO 0
    #define MODEL_1MGN 1

    /*
    * oCam-5CR-U (Ver. 1604) supported resolutions and frame rates.
    *
    * [USB 3.0 - YUV format]
    * 2592 x 1944 @ 3.75 fps, 7.50 fps
    * 1920 x 1080 @ 7.50 fps, 15 fps
    * 1280 x 960 @ 15 fps, 30 fps
    * 1280 x 720 @ 15 fps, 30 fps
    * 640 x 480 @ 30 fps, 60 fps, 90 fps, 120 fps
    * 320 x 240 @ 30 fps, 60 fps, 90 fps, 120 fps
    *
    * [USB 2.0 - YUV format]
    * 2592 x 1944 @ 3.75 fps
    * 1920 x 1080 @ 7.50 fps
    * 1280 x 960 @ 15 fps
    * 1289 x 720 @ 15 fps
    * 640 x 480 @ 30 fps, 60 fps
    * 320 x 240 @ 30 fps, 60 fps, 90 fps, 120 fps
    *
    *
    * oCam-1MGN-U (Ver. 1611) supported resolutions and frame rates.
    *
    * [USB 3.0 - GREY format]
    * 1280 x 960 @ 45 fps
    * 1280 x 720 @ 60 fps
    * 640 x 480 @ 80 fps
    * 320 x 240 @ 160 fps
    *
    * [USB 2.0 - GREY format]
    * 1280 x 960 @ 22.5 fps
    * 1280 x 720 @ 30 fps
    * 640 x 480 @ 80 fps
    * 320 x 240 @ 160 fps
    */

    static const int IMAGE_WIDTH = 640; // pixel
    static const int IMAGE_HEIGHT = 480; // pixel
    static const double IMAGE_FPS = 2; // frame per second

    /*
    * Main Function
    */
    int main(int argc, char* argv[])
    {
    int camNum = GetConnectedCamNumber();
    if (camNum==0)
    printf("Can not find oCam\n");

    int model = 0;
    char *camModel = CamGetDeviceInfo(0, INFO_MODEL_NAME);
    if (strcmp(camModel, "oCam-5CRO-U")==0)
    model = MODEL_5CRO;
    else
    model = MODEL_1MGN;

    Mat image, image_rgb;
    if (model == MODEL_5CRO)
    {
    image = Mat(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC2);
    image_rgb = Mat(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC3);
    }
    else
    {
    image = Mat(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1);
    }

    /* Create the named window for imshow. */
    const char* windowName = "oCam";
    cv::namedWindow(windowName);

    /* Open oCam */
    CAMPTR ptrCam = CamOpen(0, IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_FPS, NULL, NULL);;

    /* Start the camera */
    CamStart(ptrCam);

    int index = 0;
    char buf[256];


    while (true)
    {
    /* Get the image */
    if (CamGetImage(ptrCam, image.data))
    {
    /* Show the image */
    if (model == MODEL_5CRO)
    {
    cvtColor(image, image_rgb, CV_YUV2BGR_YUYV);
    imshow(windowName, image_rgb);
    }
    else
    {
    /* Show the image */
    imshow(windowName, image);

    /* Save the image */
    sprintf(buf, "C:/oCamTest/img_%03d.jpg", index);
    cout << buf << endl;
    imwrite(buf, image);

    index++;
    // if (index == 999999) index = 0;
    // if (waitKey(25) == 27) break;
    }
    }

    /* When pressed 'q' key then exit the loop. */
    if (waitKey(5) == 'q')
    break;
    }

    /* Stop the streamming */
    CamStop(ptrCam);

    /* Close the oCam */
    CamClose(ptrCam);

    return 0;
    }

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.03.31 18:31 신고

      waitKey 함수의 아규먼트로 조정해야 할듯합니다.

    • 질문자 2020.04.02 15:21

      답변 감사합니다.
      아규먼트를 어떻게 조정해야 하나요?
      OpenCV를 처음 사용해봐서.. 여러번 문의 드립니다..

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.04.02 15:26 신고

      waitKey의 아규먼트의 단위가 ms입니다. 30으로 하면 30ms 대기 후 웹캠으로부터 다음 프레임을 가져옵니다. 대기시간을 조정하여 1초에 몇장의 이미지를 가져올지 설정하세요.

    • 질문자 2020.04.02 15:55

      알려주신데로 설정하니 문제가 해결된 것 같습니다.
      그런데 한 가지 추가 문의사항 있습니다.
      현재 사용하고 있는 카메라는 펄스 형태의 외부 트리거를 이용하여 동작하고 있습니다. 펄스가 low (하강엣지)일 때 영상 취득을 시작하고, high (상승엣지)일 때 영상 취득을 종료합니다. 실제 카메라의 frame rate과 waitKey의 아규먼트와 어떻게 관련이 되는지 궁금합니다.

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.04.02 16:03 신고

      waitKey 함수의 아규먼트로 대기시간을 조정하여 카메라의 프레임 레이트에 맞추어 이미지를 가져오게 조정할 수 있습니다.

    • 2020.04.02 16:16

      비밀댓글입니다

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.04.02 16:29 신고

      webnautes@naver.com 입니다

  14. Jung 2020.06.12 15:46

    안녕하세요.
    포스트 잘 보았습니다.
    완전 초보인데, 포스트 따라서 그대로 하니 이미지 저장까지 잘 됩니다.
    헌데, 혹시 바코드 스캐너(USB 혹은 시리얼 포트로 연결)로 바코드(code-128)를 스캔시 이미지 저장이 되게도 할수 있을까요?
    (스캔값을 파일명으로 할 수 있으면 더 좋구요.)
    감사합니다!

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.06.12 18:39 신고

      스캐너가 동작시 카메라로 사진을 찍는 다는 건가요?

  15. Jung 2020.06.13 23:00

    죄송합니다. 제 설명이 부족했나 봅니다. 바코드 스캐너로 바코드를 스캔하여 스캔 데이터가 입력되면 카메라로 사진을 찍게 하는 게 가능할까요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.06.13 23:53 신고

      바코드 스캐너 입력을 받는 프로그램을 직접 만든다면 가능할 거 같습니다.

+ Recent posts