visual_regression.sh 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. #!/bin/bash
  2. # This script runs a visual regression test on all the images
  3. # generated from OSMD samples (npm run generate:current and npm run generate:blessed)
  4. #
  5. # inspired by Vexflow's visual regression tests.
  6. #
  7. # Prerequisites: ImageMagick
  8. #
  9. # On OSX: $ brew install imagemagick
  10. # On Linux: $ apt-get install imagemagick
  11. #
  12. # Usage:
  13. #
  14. #
  15. # First generate the known good or previous state PNG images you want to compare to, e.g. the develop branch or last release:
  16. # (Server has to be running for this: npm start)
  17. #
  18. # npm run generate:blessed
  19. #
  20. # Make changes in OSMD, then generate your new images:
  21. #
  22. # npm run generate:current
  23. #
  24. # Run the regression tests against the blessed images in tests/blessed.
  25. #
  26. # # (this should be done from the main OSMD folder)
  27. # sh test/Util/visual_regression.sh
  28. #
  29. # Check build/images/diff/results.txt for results. This file is sorted
  30. # by PHASH difference (most different files on top.) The composite diff
  31. # images for failed tests (i.e., PHASH > 1.0) are stored in build/images/diff.
  32. #
  33. # If you are satisfied with the differences, copy *.png from build/images
  34. # into tests/blessed, and submit your change.
  35. # PNG viewer on OSX. Switch this to whatever your system uses.
  36. # VIEWER=open
  37. # Show images over this PHASH threshold. This is probably too low, but
  38. # a good first pass.
  39. THRESHOLD=0.01
  40. # Directories. You might want to change BASE, if you're running from a
  41. # different working directory.
  42. BASE=.
  43. IMAGESPARENTFOLDER=$BASE/data/images
  44. BLESSED=$IMAGESPARENTFOLDER/blessed
  45. CURRENT=$IMAGESPARENTFOLDER/current
  46. DIFF=$IMAGESPARENTFOLDER/diff
  47. # All results are stored here.
  48. RESULTS=$DIFF/results.txt
  49. WARNINGS=$DIFF/warnings.txt
  50. mkdir -p $DIFF
  51. if [ -e "$RESULTS" ]
  52. then
  53. rm $DIFF/*
  54. fi
  55. touch $RESULTS
  56. touch $RESULTS.pass
  57. touch $RESULTS.fail
  58. touch $WARNINGS
  59. # If no prefix is provided, test all images.
  60. if [ "$1" == "" ]
  61. then
  62. files=*.png
  63. else
  64. files=$1*.png
  65. fi
  66. if [ "`basename $PWD`" == "Util" ]
  67. then
  68. echo Please run this script from the OSMD base directory.
  69. exit 1
  70. fi
  71. # Number of simultaneous jobs
  72. nproc=$(sysctl -n hw.physicalcpu 2> /dev/null || nproc)
  73. if [ -n "$NPROC" ]; then
  74. nproc=$NPROC
  75. fi
  76. total=`ls -l $BLESSED/$files | wc -l | sed 's/[[:space:]]//g'`
  77. echo "Running $total tests with threshold $THRESHOLD (nproc=$nproc)..."
  78. function ProgressBar {
  79. let _progress=(${1}*100/${2}*100)/100
  80. let _done=(${_progress}*4)/10
  81. let _left=40-$_done
  82. _fill=$(printf "%${_done}s")
  83. _empty=$(printf "%${_left}s")
  84. printf "\rProgress : [${_fill// /#}${_empty// /-}] ${_progress}%%"
  85. }
  86. function diff_image() {
  87. local image=$1
  88. local name=`basename $image .png`
  89. local blessed=$BLESSED/$name.png
  90. local current=$CURRENT/$name.png
  91. local diff=$current-temp
  92. if [ ! -e "$current" ]
  93. then
  94. echo "Warning: $name.png missing in $CURRENT." >$diff.warn
  95. return
  96. fi
  97. if [ ! -e "$blessed" ]
  98. then
  99. return
  100. fi
  101. cp $blessed $diff-a.png
  102. cp $current $diff-b.png
  103. # Calculate the difference metric and store the composite diff image.
  104. local hash=`compare -metric PHASH -highlight-color '#ff000050' $diff-b.png $diff-a.png $diff-diff.png 2>&1`
  105. local isGT=`echo "$hash > $THRESHOLD" | bc -l`
  106. if [ "$isGT" == "1" ]
  107. then
  108. # Add the result to results.text
  109. echo $name $hash >$diff.fail
  110. # Threshold exceeded, save the diff and the original, current
  111. cp $diff-diff.png $DIFF/$name.png
  112. cp $diff-a.png $DIFF/$name'_'Blessed.png
  113. cp $diff-b.png $DIFF/$name'_'Current.png
  114. echo
  115. echo "Test: $name"
  116. echo " PHASH value exceeds threshold: $hash > $THRESHOLD"
  117. echo " Image diff stored in $DIFF/$name.png"
  118. # $VIEWER "$diff-diff.png" "$diff-a.png" "$diff-b.png"
  119. # echo 'Hit return to process next image...'
  120. # read
  121. else
  122. echo $name $hash >$diff.pass
  123. fi
  124. rm -f $diff-a.png $diff-b.png $diff-diff.png
  125. }
  126. function wait_jobs () {
  127. local n=$1
  128. while [[ "$(jobs -r | wc -l)" -ge "$n" ]] ; do
  129. # echo ===================================== && jobs -lr
  130. # wait the oldest job.
  131. local pid_to_wait=`jobs -rp | head -1`
  132. # echo wait $pid_to_wait
  133. wait $pid_to_wait &> /dev/null
  134. done
  135. }
  136. count=0
  137. for image in $CURRENT/$files
  138. do
  139. count=$((count + 1))
  140. ProgressBar ${count} ${total}
  141. wait_jobs $nproc
  142. diff_image $image &
  143. done
  144. wait
  145. cat $CURRENT/*.warn 1>$WARNINGS 2>/dev/null
  146. rm -f $CURRENT/*.warn
  147. ## Check for files newly built that are not yet blessed.
  148. for image in $CURRENT/$files
  149. do
  150. name=`basename $image .png`
  151. blessed=$BLESSED/$name.png
  152. current=$CURRENT/$name.png
  153. if [ ! -e "$blessed" ]
  154. then
  155. echo " Warning: $name.png missing in $BLESSED." >>$WARNINGS
  156. fi
  157. done
  158. num_warnings=`cat $WARNINGS | wc -l`
  159. cat $CURRENT/*.fail 1>$RESULTS.fail 2>/dev/null
  160. num_fails=`cat $RESULTS.fail | wc -l`
  161. rm -f $CURRENT/*.fail
  162. # Sort results by PHASH
  163. sort -r -n -k 2 $RESULTS.fail >$RESULTS
  164. sort -r -n -k 2 $CURRENT/*.pass 1>>$RESULTS 2>/dev/null
  165. rm -f $CURRENT/*.pass $RESULTS.fail $RESULTS.pass
  166. echo
  167. echo Results stored in $DIFF/results.txt
  168. echo All images with a difference over threshold, $THRESHOLD, are
  169. echo available in $DIFF, sorted by perceptual hash.
  170. echo
  171. if [ "$num_warnings" -gt 0 ]
  172. then
  173. echo
  174. echo "You have $num_warnings warning(s):"
  175. cat $WARNINGS
  176. fi
  177. if [ "$num_fails" -gt 0 ]
  178. then
  179. echo "You have $num_fails fail(s):"
  180. head -n $num_fails $RESULTS
  181. else
  182. echo "Success - All diffs under threshold!"
  183. fi