snibgo's ImageMagick pages

Levels of detail

We can vary the processing across an image according to how much detail is present in the different areas.


Finding detail

The level of detail within an image may be found:

  1. Directly from a method given in Details, details.
  2. Indirectly by removing detail, simplifying the image, and comparing the simplification with the original. Where change has occurred, we had detail.

The direct method is fast and simple. The indirect method is slower and more complex, but as a byproduct makes simplified versions of the image.

Sample source images

set LD_SRC1=ld_src1.tiff

if not exist %LD_SRC1% %IM%convert ^
  \pictures\20141211\AGA_2224_sRGB.tiff ^
  -crop 4924x4924+1832+0 +repage ^

set SRC1_CROP=-crop 400x300+1426+694 +repage

Show a resize and a crop from LD_SRC1.

set WEB_SIZE=-resize 600x600

%IM%convert ^
  %LD_SRC1% ^
  ( +clone ^
    %WEB_SIZE% ^
    +write ld_src1_sm.png ^
    +delete ^
  ) ^
  %SRC1_CROP% ^
ld_src1_sm.pngjpg ld_src1_cr.pngjpg

All operations are performed on the full-size image, but smaller JPEG versions are made for the web.

The second source is already sized and sharpened for the web.

set LD_SRC2=ld_src2.png


Actual size


Removing detail

This is an iterative process. We say an input image is at level 0 (zero). A simplification of level (n) is at level (n+1). We take a difference between images at levels (n) and (n+1). Where a pixel difference is less than a threshold, it does not represent detail at level (n). Otherwise, it does. Each iteration results in four images:

Of these, the first three are made within each iteration. The reconstruction *_ldr* can only be made when the largest level of detail is known.

The script ldLevDet makes the mask *_ldm* and the detail pixels *_ldd*.

For example, if the level 0 image is LD_SRC2, and the level 1 version is ...

%IM%convert ^
  %LD_SRC2% ^
  -median 3x3 ^

... then we call ldLevDet.bat:

call %PICTBAT%ldLevDet ^
  %LD_SRC2% ld_rd_examp.png ld_rdex
ld_rdex_ldm.png ld_rdex_ldd.png

Indirect: progressive blur

Indirect: progressive medians

The script ldProgMed.bat applies a progressively larger median filter. The effect is very clean, the code is very simple and the result is very satisfying. However, it is slow. (Instead of doubling the median size, halving the image before median then resizing back afterwards probably gives a close-enough result.)

For the small image LD_SRC2, processing takes my laptop about 25 minutes.

The large image LD_SRC1 would take around one month.

set ldCNT_LIM=3
call %PICTBAT%ldProgMed %LD_SRC2% ldpm
echo %ldpmCNT% 

The outputs, numbered from 1 (one) upwards, are:

ldpm_1.pngjpg ldpm_2.pngjpg ldpm_3.pngjpg

The script ldProgs.bat calls ldLevDet.bat to create each mask *_ldm* and each detail image *_ldd*. Then it operates in the reverse direction to make each reconstruction *_ldr* image.

set LD_DEBUG=1

call %PICTBAT%ldProgs %LD_SRC2% %ldpmCNT% ldpm
ldpm_0_ldm.png ldpm_1_ldm.png ldpm_2_ldm.png ldpm_0_ldd.png ldpm_1_ldd.png ldpm_2_ldd.png ldpm_0_ldr.png ldpm_1_ldr.png ldpm_2_ldr.png


For convenience, .bat scripts are also available in a single zip file. See Zipped BAT files.


rem Given %1 and %2 are two images,
rem where %1 has more detail than %2
rem make a difference mask, white where there is more detail,
rem and re-constituted image of %1 plus the extra detail.
rem %3 is prefix for outputs.
rem %4 is radius for smoothing.

@if "%3"=="" findstr /B "rem @rem" %~f0 & exit /B 1

@setlocal enabledelayedexpansion

@call echoOffSave

call %PICTBAT%setInOut %1 ldld

if "%ldEXT%"=="" set ldEXT=png

if "%ldTHRESH%"=="" set ldTHRESH=90

set MASK=%3_ldm.%ldEXT%
set NEWPIX=%3_ldd.%ldEXT%
set RECON=%3_x.%ldEXT%

if "%4"=="" (
  set SMOOTH=
) else (
  set SMOOTH=-morphology Smooth Disk:%4

%IM%convert ^
  %2 %1 ^
  ( -clone 0-1 ^
    -compose Difference -composite ^
    -grayscale RMS -contrast-stretch %ldTHRESH%%%x0 -fill White +opaque Black ^
    %SMOOTH% ^
    +write %MASK% ^
  ) ^
  ( -clone 1-2 ^
    -compose CopyOpacity -composite ^
    +write %NEWPIX% ^
  ) ^
  -delete 1-2 ^
  -compose Over -composite ^

rem The mask could be further processed before use:
rem - remove small black specks within white
rem - remove small white specks
rem - merge adjacent white marks
rem The limits will depend on the brush size at this detail.

call echoRestore


rem     -morphology Smooth Disk:1


rem From image %1,
rem make progressive median versions.
rem %2 is prefix for output files.

@if "%2"=="" findstr /B "rem @rem" %~f0 & exit /B 1

@setlocal enabledelayedexpansion

REM 	@call echoOffSave

call %PICTBAT%setInOut %1 ldpm

if "%ldEXT%"=="" set ldEXT=png

if "%ldSTART_MED%"=="" set ldSTART_MED=3

if "%ldCNT_LIM%"=="" set ldCNT_LIM=20

set WW=
for /F "usebackq" %%L in (`%IM%identify ^
  -format "WW=%%w\nHH=%%h\nMINDIM=%%[fx:w<h?w:h]" ^
  %INFILE%`) do set %%L
if "%WW%"=="" exit /B 1

set CNT=1
set OPTS=


set OUTFILE=%2_!CNT!.%ldEXT%
echo %OUTFILE%
set OPTS=!OPTS! ( -clone 0 -median !MED_SQ!x!MED_SQ! +write %OUTFILE% +delete )

echo MED_SQ=!MED_SQ!

set /A MED_SQ=MED_SQ*2+1
set /A CNT+=1

if !CNT! LEQ %ldCNT_LIM% if !MED_SQ! LSS %MINDIM% goto loop

echo %OPTS%

%IM%convert ^
  %INFILE% ^
  %OPTS% ^

set /A CNT-=1

call echoRestore

@endlocal & set ldpmCNT=%CNT%


rem from image %1
rem and %2 images with prefix %3,
rem makes mask and detail images.
rem Then builds the reconstruction images.

@if "%3"=="" findstr /B "rem @rem" %~f0 & exit /B 1

@setlocal enabledelayedexpansion

rem @call echoOffSave

call %PICTBAT%setInOut %1 ldps

set /A CNT=%2
set /A CNTm1=%2-1

set PREFIX=%3

if "%ldEXT%"=="" set ldEXT=png

goto skip
for /L %%i in (0,1,%CNTm1%) do (
  set /A Ip1=%%i+1
  set IN0=%PREFIX%_%%i.%ldEXT%
  set IN1=%PREFIX%_!Ip1!.%ldEXT%
  if %%i==0 set IN0=%INFILE%
  call %PICTBAT%ldLevDet !IN0! !IN1! %PREFIX%_%%i 1

rem Make the reconstructions.

set OPTS=

for /L %%i in (%CNTm1%,-1,0) do (
  set /A Ip1=%%i+1
  set IN0=%PREFIX%_%%i.%ldEXT%
  set IN1=%PREFIX%_!Ip1!.%ldEXT%
  if %%i==0 set IN0=%INFILE%
  call %PICTBAT%ldLevDet !IN0! !IN1! %PREFIX%_%%i 1

  echo i=%%i
  set INNAME=%PREFIX%_%%i_ldd.%ldEXT%
  set OUTNAME=%PREFIX%_%%i_ldr.%ldEXT%
  set OPTS=!OPTS! ^( +clone 0 !INNAME! -composite +write !OUTNAME! ^)
echo !OPTS!

%IM%convert %PREFIX%_%CNT%.%ldEXT% !OPTS! NULL:

if "%LD_DEBUG%"=="1" (

echo on

  rem Make a stacked illustration.

  for /F "usebackq" %%L in (`%IM%identify ^
    -format "WW=%%w\nHH=%%h\nDX=%%[fx:int(w/4.5+0.5)]\nDY=%%[fx:int(w/6.5+0.5)]" ^
    %INFILE%`) do set %%L

  echo DX,DY=!DX!,!DY!

  set OPTS=

  for /L %%i in (%CNTm1%,-1,0) do (
    echo i=%%i
    set /A RX=^(!CNT!-%%i^)*!DX!
    set /A RY=^(!CNT!-%%i^)*!DY!
    set FNAME=%PREFIX%_%%i_ldd.%ldEXT%
    set OPTS=!OPTS! ^( !FNAME! -repage +!RX!+!RY! ^)
  echo !OPTS!

  %IM%convert %PREFIX%_%CNT%.%ldEXT% !OPTS! -layers merge %PREFIX%_dbg.%ldEXT%

All images on this page were created by the commands shown, using:

%IM%identify -version
Version: ImageMagick 6.9.0-0 Q16 x64 2014-11-14
Copyright: Copyright (C) 1999-2014 ImageMagick Studio LLC
Features: DPC OpenMP
Delegates (built-in): bzlib cairo freetype jbig jng jp2 jpeg lcms lqr pangocairo png ps rsvg tiff webp xml zlib

Source file for this web page is levdet.h1. To re-create this web page, execute "procH1 levdet".

This page, including the images, is my copyright. Anyone is permitted to use or adapt any of the code, scripts or images for any purpose, including commercial use.

Anyone is permitted to re-publish this page, but only for non-commercial use.

Anyone is permitted to link to this page, including for commercial use.

Page version v1.0 23-Feb-2015.

Page created 26-Feb-2015 03:00:41.

Copyright © 2015 Alan Gibson.