-
Notifications
You must be signed in to change notification settings - Fork 6
/
analyze.sh
executable file
·328 lines (290 loc) · 11.3 KB
/
analyze.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
#!/bin/bash
#
# Statistical helper functions for greyscale images.
#
# Requirements: ImageMagick's identify and convert
#
# If true, input files are assumed to be greyscale.
# If false, they are converted to greyscale before extracting statistics.
if [ "." == ".$ASSUME_GREY" ]; then
ASSUME_GREY=true
fi
# Prints width and height of the given image, separated by space
# Input: Image
function isize() {
identify -format "%w %h" "$1"
}
export -f isize
# TODO: Accept destination for identify-file as input
# TODO: If FORCE_HISTOGRAM is true, cached identify-files should be deleted
# to ensure CROP_PERCENT is used
# Input: image [destination]
# Sample: foo.png
# Produces foo.identify if not already existing.
# Output: The name of the identity file
function im_identify() {
local SRC="$1"
if [ -n "$2" ]; then
local DEST_FOLDER="$2"
else
local DEST_FOLDER=$(dirname "$SRC")
fi
local BASE=${SRC##*/}
local IDENTIFY=${DEST_FOLDER}/${BASE%%.*}.identify
if [ -f "$IDENTIFY" ]; then
echo "$IDENTIFY"
return
fi
if [ "false" == "$ASSUME_GREY" ]; then
# We do the TIFF-conversion to force greyscale
local TMP=`mktemp --suffix .tif`
if [ "." == ".$CROP_PERCENT" ]; then
gm convert "$SRC" -colorspace gray "$TMP"
else
gm convert "$SRC" -gravity Center -crop $CROP_PERCENT%x+0+0 -colorspace gray "$TMP"
fi
identify -verbose "$TMP" > "$IDENTIFY"
rm "$TMP"
else
if [ "." == ".$CROP_PERCENT" ]; then
identify -verbose "$SRC" > "$IDENTIFY"
else
local TMP=`mktemp --suffix .tif`
gm convert "$SRC" -gravity Center -crop $CROP_PERCENT%x+0+0 "$TMP"
identify -verbose "$TMP" > "$IDENTIFY"
rm "$TMP"
fi
fi
echo "$IDENTIFY"
}
export -f im_identify
# Outputs all the greyscale values and their counts
# Input: Image [destination]
function greys() {
local IFILE=`im_identify "$1" "$2"`
local VALUES=`cat "$IDENTIFY" | grep -A 256 Histogram`
if [ ! "." == ".`grep Colormap "$IFILE"`" ]; then
cat "$IFILE" | grep -A 257 Histogram | grep -B 256 Colormap | grep "[0-9]\\+: ("
else
cat "$IFILE" | grep -A 256 Histogram | grep "[0-9]\\+: ("
fi
}
export -f greys
# TODO: Accept destination for grey-stats-file as input
# Input: image
# Sample: foo.png
# Produces foo.grey with $PIXELS $UNIQUE $FIRST_COUNT $PERCENT_FIRST $FIRST_GREY $LAST_COUNT $PERCENT_LAST $LAST_GREY
# Output: $PIXELS $UNIQUE $FIRST_COUNT $PERCENT_FIRST $FIRST_GREY $LAST_COUNT $PERCENT_LAST $LAST_GREY $ZEROES $HOLES
function grey_stats() {
local SRC="$1"
if [ -n "$2" ]; then
local DEST_FOLDER="$2"
else
local DEST_FOLDER=$(dirname "$SRC")
fi
if [ ! -f "$SRC" ]; then
echo "grey_stats: The file $SRC does not exist in `pwd`" 1>&2
return
fi
local IDENTIFY=$(im_identify "$SRC" "$DEST_FOLDER")
local BASE=${SRC##*/}
local GREY=${DEST_FOLDER}/${BASE%%.*}.grey
local INFO=`cat "$IDENTIFY"`
local RAW_VALUES=`greys "$SRC" "$DEST_FOLDER"`
# TODO: No good as the histogram data might be much less than 256
# local VALUES=`cat "$IDENTIFY" | grep -A 256 Histogram`
# if [ ! "." == ".`echo "$VALUES" | grep Colormap`" ]; then
# local VALUES=`echo "$VALUES" | grep -B 256 Colormap`
# fi
# local RAW_VALUES=`echo "$VALUES" | grep "[0-9]\\+: ("`
# local VALUES="$INFO"
# ***
# local SAVEIFS=$IFS
IFS=$(echo -en $"\n")
local UNIQUE=`echo "$RAW_VALUES" | wc -l`
local FIRST_REAL_GREY=`echo "$RAW_VALUES" | head -n 1 | sed 's/.* ( *\([0-9]\+\),.*/\1/'`
local UNIQUE_DARKS=0
if [ ! "1,1,1" == ".$BLOWN_BLACK_BT" ]; then
# TODO: Add skipping based on BLOWN_BLACK_WT
local FIRST_COUNT=0
local MAXG=`echo "$BLOWN_BLACK_BT" | grep -o "^[^,]\+"`
# echo "$RAW_VALUES" | head -n $MAXG
IFS=$(echo -en $"\n\b")
for E in `echo "$RAW_VALUES" | head -n $MAXG`; do
# echo "e:$E"
# 81422: ( 0, 0, 0) #000000 black
local C=`echo "$E" | grep -o " [0-9]\\+:" | grep -o "[0-9]\\+"`
local G=`echo "$E" | grep -o ": \\+([^0-9]*[0-9]\\+," | grep -o "[0-9]\\+"`
# echo "c:$C g:$G t:$MAXG"
if [ "$G" -lt "$MAXG" ]; then
local UNIQUE_DARKS=$((UNIQUE_DARKS+1))
local FIRST_COUNT=$((FIRST_COUNT+$C))
local LAST_VALID=$G
fi
done
local FIRST_GREY="0-$LAST_VALID"
#local FIRST_GREY=`echo "$E" | head -n 1 | grep -o " ([0-9 ,]*)" | sed 's/ //g'`
else
local UNIQUE_DARKS=1
local FIRST_GREY=`echo "$RAW_VALUES" | head -n 1 | sed 's/.* ( *\([0-9]\+\),.*/\1/'`
local FIRST_COUNT=`echo "$RAW_VALUES" | head -n 1 | grep -o " [0-9]\\+:" | grep -o "[0-9]\\+"`
fi
if [ 0 -eq "$FIRST_COUNT" ]; then
# No pixels from 0-fuzzy_factor
local UNIQUE_DARKS=1
local FIRST_GREY=`echo "$RAW_VALUES" | head -n 1 | sed 's/.* ( *\([0-9]\+\),.*/\1/'`
local FIRST_COUNT=`echo "$RAW_VALUES" | head -n 1 | grep -o " [0-9]\\+:" | grep -o "[0-9]\\+"`
fi
IFS=$(echo -en $"\n")
local LAST_COUNT=`echo "$RAW_VALUES" | tail -n 1 | grep -o " [0-9]\\+:" | grep -o "[0-9]\\+"`
local LAST_GREY=`echo "$RAW_VALUES" | tail -n 1 | sed 's/.* ( *\([0-9]\+\),.*/\1/'`
local ZEROES=$((256-UNIQUE))
local SPAN=$((LAST_GREY-FIRST_REAL_GREY+1))
local EDGE=$((256-SPAN))
local HOLES=$((ZEROES-EDGE))
# TODO: Also remove lightest
local REDUCED=`skipLines "$RAW_VALUES" $UNIQUE_DARKS`
local REDUCED=`skipLines "$REDUCED" -1`
local SPIKE_LINE=`echo "$REDUCED" | sort -n | tail -n 1`
local SPIKE_COUNT=`echo "$SPIKE_LINE" | grep -o " [0-9]\\+:" | grep -o "[0-9]\\+"`
local SPIKE_GREY=`echo "$SPIKE_LINE" | sed 's/.* ( *\([0-9]\+\),.*/\1/'`
local GEOMETRY=`echo $INFO | grep "Geometry: [0-9]\\+x[0-9]\\+" | grep -o "[0-9]\\+x[0-9]\\+"`
local X=`echo $GEOMETRY | grep -o "[0-9]\\+x" | grep -o "[0-9]\\+"`
local Y=`echo $GEOMETRY | grep -o "x[0-9]\\+" | grep -o "[0-9]\\+"`
local PIXELS=`echo "$X*$Y" | bc`
# http://stackoverflow.com/questions/8402181/how-do-i-get-bc1-to-print-the-leading-zero
local PERCENT_FIRST=`echo "scale=2;x=$FIRST_COUNT*100/$PIXELS; if(x<1) print 0; x" | bc`
local PERCENT_LAST=`echo "scale=2;x=$LAST_COUNT*100/$PIXELS; if(x<1) print 0; x" | bc`
local SPIKE_PERCENT=`echo "scale=2;x=$SPIKE_COUNT*100/$PIXELS; if(x<1) print 0; x" | bc`
echo "$PIXELS $UNIQUE $FIRST_COUNT $PERCENT_FIRST $FIRST_GREY $LAST_COUNT $PERCENT_LAST $LAST_GREY" > "$GREY"
IFS=$SAVEIFS
echo "$PIXELS $UNIQUE $FIRST_COUNT $PERCENT_FIRST $FIRST_GREY $LAST_COUNT $PERCENT_LAST $LAST_GREY $SPIKE_COUNT $SPIKE_PERCENT $SPIKE_GREY $ZEROES $HOLES"
}
#http://stackoverflow.com/questions/5799303/print-a-character-repeatedly-in-bash
# Input: char num
printChar() {
str=$1
num=$2
v=$(printf "%-${num}s" "$str")
echo "${v// /*}"
}
export -f printChar
# Produces a histogram over greyscale intensities in the given image
# Input: image height log [destination]
# Sample: foo.jpg 200 true foo.hist.png
# Output: foo.png (256 x height pixels) with the histogram
function histogramScript() {
local SRC="$1"
local HEIGHT=$2
local LOG=$3
local DEST="$4"
local IDENTIFY_DEST=$(dirname ${DEST})
local IDENTIFY=`im_identify "$SRC" "$IDENTIFY_DEST"`
if [ ! -n "$DEST" ]; then
local DEST=${SRC%%.*}.histogram.png
fi
# Convert
# 78085: ( 0, 0, 0) #000000 black
# 3410: ( 1, 1, 1) #010101 rgb(1,1,1)
# into
# 0 78085
# 1 3410
GREYS=`greys "$SRC" | sed 's/ \\+\\([0-9]\\+\\): ( *\\([0-9]\\+\\).\\+/\\2 \\1/g'`
# Find lowest and highest for both intensity and count
local MIN_GREY=255
local MAX_GREY=0
local MIN_COUNT=9999999
local MAX_COUNT=0
local TOTAL_COUNT=0
# Speedup-trick: Read one line of a time instead of splitting up front with for-loop
while IFS= read -r L
do
set -- junk $L
shift
# local GREY=`echo "$L" | cut -d\ -f1`
# local COUNT=`echo "$L" | cut -d\ -f2`
local GREY=$1
local COUNT=$2
local TOTAL_COUNT=$((TOTAL_COUNT+COUNT))
if [ $MIN_GREY -gt $GREY ]; then
local MIN_GREY=$GREY
fi
if [ $MAX_GREY -lt $GREY ]; then
local MAX_GREY=$GREY
fi
if [ $MIN_COUNT -gt $COUNT ]; then
local MIN_COUNT=$COUNT
fi
if [ $MAX_COUNT -lt $COUNT ]; then
local MAX_COUNT=$COUNT
fi
done <<< "$GREYS"
# echo "Grey: $MIN_GREY $MAX_GREY count: $MIN_COUNT $MAX_COUNT $TOTAL_COUNT"
if [ -n "$HISTOGRAM_PHEIGHT" ]; then
if [ ! "auto" == "$HISTOGRAM_PHEIGHT" ]; then
if [ ! "script_auto" == "$HISTOGRAM_PHEIGHT" ]; then
local HH=`echo "$HISTOGRAM_PHEIGHT" | grep -o "[0-9]\+"`
local MAX_COUNT=$((HH*TOTAL_COUNT/100))
fi
fi
fi
# Let SCALE map all counts from 0 to 100000000 (giga)
if [ ".true" == ".$LOG" ]; then
local SCALE=`echo "1000000000/l($MAX_COUNT)" | bc -l`
# local SCALE=`echo "scale=10;1/l($MAX_COUNT)" | bc -l`
else
local SCALE=$((1000000000/MAX_COUNT))
# local SCALE=`echo "scale=10;1/$MAX_COUNT" | bc -l`
fi
# We create a PGM-file with the extracted greyscale statistics
# as a histogram. The PGM is sideways because it is easier
# http://netpbm.sourceforge.net/doc/pgm.html
local HTMP=`mktemp --suffix .pgm`
if [ "true" == "$LOG" ]; then
local NONE=1
else
local NONE=0
fi
echo "P5 $HEIGHT 256 255" > $HTMP
# Speedup-tricks: Avoid forking as much as possible by doing arithmetic
# with the built-in $(()). Avoid floating point by scaling up.
# Output 0 and ff with printf instead of loop.
for G in `seq 0 255`; do
local LINE=`echo "$GREYS" | grep "^$G "`
# http://stackoverflow.com/questions/1469849/how-to-split-one-string-into-multiple-strings-in-bash-shell
set -- junk $LINE
shift
COUNT=$2
# local COUNT=`echo "$GREYS" | grep "^$G " | sed 's/[0-9]\\+ \\([0-9]\\+\\)/\\1/g'`
if [ "." == ".$COUNT" ]; then
local COUNT=$NONE
fi
if [ $COUNT -gt $MAX_COUNT ]; then
local COUNT=$MAX_COUNT
fi
if [ ".true" == ".$LOG" ]; then
local PIXELS=`echo "scale=10;l($COUNT)/l(10)*$SCALE*$HEIGHT" | bc -l`
local PIXELS=`echo "scale=0;$PIXELS/1" | bc -l`
# local PIXELS=`echo "scale=10;l($COUNT)/l(10)*$SCALE*$HEIGHT/1000000000" | bc -l`
else
local PIXELS=$(($COUNT*$SCALE*$HEIGHT/1000000000))
# local PIXELS=`echo "scale=10;$COUNT*$SCALE*$HEIGHT" | bc -l`
fi
# /1 due to funky bc scale not being applied if nothing is done
# local PIXELS=`echo "scale=0;$PIXELS/1" | bc -l`
printf %$((PIXELS))s |tr " " '\0' >> $HTMP
# 377 octal = ff hex
printf %$((HEIGHT-PIXELS))s |tr " " '\377' >> $HTMP
# echo "$G $COUNT $PIXELS"
done
# echo "convert $HTMP -rotate 270 $DEST"
convert $HTMP -rotate 270 "$DEST"
# ls -l $HTMP
rm $HTMP
}
export -f histogramScript
#export HISTOGRAM_PHEIGHT="10%"
#time histogramScript $1 200 false
#time histogramScript $1 200 false
#time histogramScript $1 200 false
# grey_stats $1