imageMagick 변환 기능을 사용하여 여러 이미지(약 1백만 개)의 크기를 조정하고 싶습니다. 우분투 16.04를 사용하고 있습니다
생각보다 시간이 오래 걸렸습니다. (약 5시간 동안 진행되었습니다. 5시간을 더 줄 수도 있었지만 멈추고 싶었습니다.)
내 질문은: 프로그램을 중지하면 이미지 손상을 걱정해야 합니까? 아니면 프로그램이 안전한 방식으로 중지됩니까?
이것은 내 스크립트입니다.
find . -name "*.JPEG" | xargs -I {} convert {} -resize "256^>" {}
(기본적으로 imagenet 데이터 세트의 크기를 조정하고 있습니다)
Ctrl-C를 누르면 일부 이미지가 손상되나요?
답변1
이론적으로는 아니요, 이미지가 손상되어서는 안 됩니다. 메모리에서 imagemagick
처리가 완료된 후 선택한 대상 파일로 이름이 바뀌는 임시 파일을 사용할 수 있다고 생각합니다 .
그런데, 당신이 한 방식으로 이미지를 변환하는 것은 단방향 작업입니다. 당신이 그것을 알아 차린 것 같아서 제 질문입니다.
마지막으로 변환된 이미지를 찾으려면 최신 파일부터 시간순으로 파일을 나열하세요. 파일 크기에 눈에 띄는 차이가 있는 경우 다음에 시작할 위치를 쉽게 알 수 있습니다. 그렇지 않으면 다음을 사용하여 이미지 크기를 검색해야 합니다.이미지매직 로고.
또한 백만 개의 이미지에 대해 각 이미지가 1초 안에 처리된다면 여전히 대략적인 시간이 소요됩니다.280시간가서 끝내세요! 빠르고 강력한 기계를 가지기를 바랍니다...
편집: 진행 상황을 보여주고 싶다면, 이것이 내가 생각할 수 있는 것입니다.마틴의 대답:
mkdir -p thumbs; \
COUNT=$(find -name "*.JPEG" | wc -l); \
find -name "*.JPEG" | while read IMG; do \
printf "\n$(( ++i )) / $COUNT\n" && \
[ -s "thumbs/${IMG%.JPEG}-small.jpg" ] || \
convert "$IMG" -resize "256^>" "thumbs/${IMG%.JPEG}-small.jpg"; \
done
이것이 하는 일:
- 썸네일 디렉토리 생성...
- 총 이미지 수를 센다
.JPEG
... - 각 이미지마다...
- 현재 이미지 파일 인덱스와 전체 인덱스를 인쇄합니다...
- 이미지가 아직 변환되지 않은 경우...
- 썸네일을 만들어 보세요.
크기를 조정할 모든 이미지가 동일한 디렉토리에 있다고 가정하고, 해당 썸네일로 인해 메인 디렉토리가 복잡해지지 않도록 썸네일을 보관하는 하위 디렉토리를 사용합니다. 그렇지 않으면 thumbs/
첫 번째 행과 다섯 번째 및 여섯 번째 행의 하위 디렉터리를 삭제할 수 있습니다 .
이미지가 하위 디렉터리에 분산되어 있는 경우:
COUNT=$(find -name "*.JPEG" | wc -l); \
find -name "*.JPEG" | while read IMG; do \
printf "\n$(( ++i )) / $COUNT\n" && \
[ -s "${IMG%.JPEG}-small.jpg" ] || \
convert "$IMG" -resize "256^>" "${IMG%.JPEG}-small.jpg"; \
done
읽기가 줄 바꿈에서 중지되므로 이 스크립트는 파일 이름의 공백을 고려합니다.
답변2
이런 식으로 합계를 합치는 것은 find
좋은 생각이 아닙니다. xargs
명령줄에서 특별한 의미를 갖는 공백 및 기타 문자가 포함된 파일 이름은 혼동을 일으킬 수 있습니다. 사용하기 가장 좋습니다
find . -name '.JPEG' -print -exec convert '{}' -resize "256^>" '{}-small.jpg' \;
명령을 실행하면 이미지를 덮어쓰는 것 같습니다. 맞습니까? 문제는 convert
꼭 그렇지는 않다는 것이다.원자적 연산. 다음과 같이 하면 훨씬 더 좋을 것입니다.
shopt -s extglob
for i in **/*.jpg; do
convert "$i" -resize "256^>" tmp.jpg
mv tmp.jpg "$i"
done
명령 mv
은 원자적일 가능성이 높습니다. 어디에서나 프로세스를 중단하면 유일한 피해는 어딘가를 헤매는 것일 수 있습니다 tmp.jpg
.
지금 누르면 명령이 CtrlC취소될 수 있습니다 . convert
인터럽트 신호가 걸리면 이미지 쓰기가 완료되지만 쓰기가 중단될 수도 있습니다.
전체 디렉토리 구조를 다른 곳으로 이동할 수 있으며 운이 좋으면 쓰기가 완료되지만 새 convert
호출은 실패합니다.
이 과정이 얼마나 진행되었는지 확인해 보는 것은 어떨까요? find
순서화된 출력을 제공하지 않으므로 디렉터리에 있는 이미지 크기를 스캔하여 크기가 조정된 이미지 수를 확인해야 합니다.
답변3
내가 이해한 바에 따르면 (그리고 잘못된 것이 있으면 나를 바로잡을 수 있는 충분한 사람들이 있다고 확신합니다) Ctrl+C는 SIGINT
실행 중인 스크립트와 하위 프로세스/스레드뿐만 아니라 bash에도 전송됩니다.
Bash는 제어권을 다시 얻는 다음 시점(예: 다음 루프 반복 또는 파이프를 통해 호출할 때)에 스크립트를 중단하고, 다른 프로세스는 신호를 받고 자체 정책(있는 경우)에 따라 종료됩니다.
데이터 손실의 실제 위험이 있는지 여부는 convert
데이터를 얼마나 적절하게 포착하고 처리하는지 에 따라 달라집니다 SIGINT
. 잘 작성된 코드(그리고 convert
한동안 그랬습니다)는 이를 적절하게 처리하고 손상 없이 종료할 수 있습니다.
ps -eT | grep -i convert
실행 중인 스레드 수와 "위험에 처한" 이미지 수를 표시해야 합니다. 쓰기 주기가 이미지당 처리 시간보다 훨씬 짧다는 점을 고려하면 convert
불행하게도 하나 또는 두 개 이상의 이미지가 단순하게 손상될 수도 있습니다. 신호가 도착했을 때 모든 것이 떨어졌습니다.