스캐너를 이용한 프로젝트 - ofImage / ofFile / OpenFrameworks 구조 관련 질문

[전제 조건]

  1. 스캐너에서 스캔을 하면 특정 이름의 이미지 파일로 파일을 생성합니다.
  2. 파일의 이름은 순서대로 이름 뒤에 숫자가 붙게 됩니다.

위의 조건을 참고하고, 아래의 사진과 같이 프로그램을 개발했습니다.

참고로, current_time 할당 부분부터는 update함수에서 그 전은 setup함수에서 진행했습니다. 그리고 스캐너처럼 사진을 복사 붙여넣기하는 스크립트를 2초마다 작동하게 만들었습니다.CopyPictures.zip (284 바이트)

하지만 여러번 정상 작동하다가 ofImage::load에서 에러가 나더군요.
로그를 살펴보면 이미지 제거 성공, 파일 존재 여부 검사 다 성공인데 load함수에서 loadImage(): couldn’t load image From “imagePath”… 이런식으로 에러가 뜹니다.

반면, 스크립트 시간을 2초에서 4초마다 복사 붙여넣기하는 방식으로 바꾸니 몇시간이 지나도 정상 작동 하더군요.
사수님께서는 update함수가 다 돌기전에 update함수가 또 돌아서 그런 문제가 생긴거라고 하시는데 원래 setup함수 1회 -> update 함수 -> draw 함수 -> update 함수 -> draw 함수… 이런식으로 무한 루핑되면서 절차적으로 진행되지 않나요?

  • 영상처리는 update함수를 사용하는게 맞는거 같지만 지금 하는 이미지 작업은 setup에서 하는게 맞다고 하십니다.

제가 궁금한 점을 다시 정리하자면

  1. 이미지 제거 및 파일 존재 체크 함수에서 TRUE를 반환해주는데 ofImage::load()에서 간혈적으로 실패가 되면서 프로그램이 강제 종료 되는 이유와 해결방법

  2. 사수분께서 말씀하신것처럼 update 함수가 thread처럼 동시에 여러개(?)가 도는지와 제가 이해한 구조가 맞는지

  3. 마지막에 +부분처럼 setup에서 무한루핑돌면서 파일 검사 및 이미지 분석 작업을 진행하는게 맞는지

일단은 update()->draw()->update()->draw() 이런식으로 정확하게 동작하게 하려면
ofSetVerticalSync(true) 를 setup에 넣어보시기 바랍니다.

이 세팅이 없으면 draw()함수는 시스템이 그려낼 수 있는 최대의 속도로 실행됩니다.
아래 링크를 참고하시기 바랍니다.

그리고 OF는 싱글 스레드로 동작합니다.

마지막으로 스캔한 파일을 복사하는 스크립트를 외부가 아닌 bat파일로 작성한 이유가 있으신지요? 직접 update()에서 처리해도 될것 같은데요.

정확하게는 모르겠으나, bat에서 파일을 복사하여 쓰는도중 이미지를 불러오면서 정상적인 로드가 안되는건 아닐지요 ? 파일을 복사하는 루틴과 이미지를 불러오는 타이밍을 명확히 해야할것 같습니다.

사실 draw는 상관없습니다.
update함수가 실행되는 도중에 update함수가 또 실행되는지 여부가 궁금합니다.

그리고, bat으로 외부에서 작성한 이유는 스캐너 역할을 위한 테스트 스크립트이기때문입니다.
프로그램내에서는 스캐너가 파일을 생성하는 타이밍을 몰라서 update함수에서 파일 체크를 하여 파일 여부에따라 이미지 처리를하는 방식으로 개발 하였습니다.

하지만, 게시글에도 적은듯이 성공적으로 작동하다가 간간히 파일이 존재한다고 doesFileEixst함수에서 반환을 해주지만 ofImage::load에서 실패하는 경우가 생깁니다.

update()도중 update()가 실행될 리가 없을텐데요.

그리고 제가 생각하는 에러 발생의 이유를 좀 더 상세하게 설명해보면 다음과 같습니다.

  1. 스캐너가 스캔후 파일을 쓰고 있다.
  2. ofFile::doesFileExist()에서 true를 리턴
  3. ofImage::load() -> 실패
  4. 스캐너가 파일 쓰기를 끝냄

ofImage::load() 레퍼런스에서 보시듯, 해당함수에서 이미지로드의 성공여부를 bool로 리턴해주므로, 로드가 실패했을시에 다시 파일을 확인해보는 방법등으로 해결을 해보시는건 어떨지요 ?

bat 을 사용하시는것 보면 윈도우 운영체제를 사용하시는것 같은데
스캐너가 파일을 저장할때 어떤 순서로 저장 하는지 또한 확인해보시기 바랍니다.

XXXXX.tmp로 저장하다가 jpg로 저장을 하는지,
아니면 .jpg로 파일을 열고 쓴다음 저장을 하는지요.

우선 아래의 저장 방식에 대해서 답변 드리겠습니다.
전제 조건을 보시면 스캐너 저장 방식을 작성해 놓았습니다.
‘스캔 이미지 보정 후 저장’ 옵션을 키면 말씀하신것처럼 저장하는걸로 알고 있습니다. 하지만 해당 옵션은 꺼놨고, 스캐너가 현재 자리에 없어서 스트레스 테스트용으로 윈도우 bat 스크립트를 작성한 것입니다.

혹시, 말씀하신 것처럼 tmp -> jpg로 저장하면 뭔가 다른점이 있나요??

그리고, 말씀하신대로 load 실패시 reference timer 시간을 바꾸지 않고, 로그만 찍도록 해놨습니다. 즉 update 함수의 처음으로 돌아가서 load를 다시 해야할터인데 load에서 해당 에러가 뜨면 바로 종료가 되거나 몇차례 해당 증상이 일어난 후에 종료가 되어버립니다.

+몇차례 해당 증상이 일어난 다는 것은 해당 로그를 남기고 성공 후에 다시 몇차례 정상 작동하다가 다시 해당 에러 로그를 남기는 동작이 몇차례 반복되는걸 의미합니다.

제가 생각하는 에러의 이유는 파일을 쓰는동안 load()가 동작할때입니다.
tmp로 저장한 뒤 파일명만 jpg로 바꾼다면 doesFileExists()에서 true가 반환될경우 이미지가 정상일 가능성이 크죠. 반대로 jpg로 바로 쓴다면 doesFileExists()가 true이다 하더라도 (이미지를 쓰는데 시간이 걸린다 가정하면) 실제 이미지는 정상적이지 않을 가능성이 크구요.

load()에서 에러가 떴을때 종료가 되는 이유는 정확히 모르겠네요.

혹시, OF에는 try-catch가 불가능할까요?
load 반환값에 따라 로그만 출력하고 update함수내에서 load하는지라 계속 load시도를 해야하는데 loadImage(): couldn’t load image From “imagePath”라는 에러만 뜨면 update함수를 다시 돌지 않고, 프로그램이 종료되네요.


이런 글을 찾았는데
ofImage::load는 내부적으로 loadImage()를 호출하고 해당 함수는 성공여부를 반환하지 프로그램을 종료시키지 않지만, 파일 접근에 문제 발생시 null이 반환되어 nullptrexception이 뜰 수 있다라고하는데 (https://processing.org/reference/loadImage_.html)

null처리를 어떻게 시켜야하나요??

저건 오픈프레임웍스가 아니라 프로세싱의 loadImage()네요

OF 는 소스코드로 배포되기 때문에 내부 코드를 직접 다 추적해서 볼 수 있습니다.

ofImage::load()는 아래에서 보실 수 있습니다.

ofLoadImage()

결국 loadImage()를 호출합니다

저도 아주 세부적으로까진 알수 없어서… 오픈프레임웍스 영문포럼 에 질문하시는데 제일 빠를것 같네요. oF개발자들이 상주하는 곳이라서 바로 답변을 얻으실 수 있을겁니다.

손상된 (다시말해 완전한 이미지로 인식되지 않는 ) 이미지 파일을 해결한 글이 있네요
한번 살펴보세요

자료 링크 감사합니다.
해당 게시글을 읽어보니 freeimage를 따로 버전 3.10 으로 업데이트하니 작동했다는거 같은데 아쉽게도 제가 사용하는 OF의 freeimage 버전은 3.18인거 같습니다.