Page 1 of 1

Cut image in horizontal slices

Posted: 2019-06-12T03:41:40-07:00
by godfried76
Hi,

I'm new to ImageMagick and hope someone could help me. I'm looking for a command / script which could automatically split an image with music score into smaller image files with the individual bars.

So somehow, the programme should detect horizontal bars with all white pixels. Those are the places where the image can be "chopped" into pieces.

Source file:
Image

Resulting files:
Image

Image

Image

Image

Can anybody please help me? Thanks!

Mathias

Re: Cut image in horizontal slices

Posted: 2019-06-12T04:30:53-07:00
by snibgo
What verson of IM, on what platform? I have Windows BAT scripts for this at Subimage rectangles . I think Fred has bash scripts for this at http://www.fmwconcepts.com/imagemagick/index.html

Re: Cut image in horizontal slices

Posted: 2019-06-12T04:40:15-07:00
by godfried76
Windows.

Impressive collection of BAT-files you have there. I'll take a look. Thanks!

Re: Cut image in horizontal slices

Posted: 2019-06-12T08:23:22-07:00
by fmw42
One way is to average your images down to 1 column. Then scan the column for the middle of pure white (or max gray level) and split there. You will have to combine the titles back with the first bar.

Re: Cut image in horizontal slices

Posted: 2019-06-12T12:59:47-07:00
by godfried76
In the end, I couldn't get the bat-scripts to work. Always error messages.

So I installed a linux virtual machine and used this script, which I found on the forum. It NEARLY does what I want!

#!/bin/bash

cd ~
cd Afbeeldingen
WxH=`convert 043-lg.jpg -format "%wx%h" info:`
cropArr=(`convert 043-lg.jpg -blur 0x3 \
-scale 1x! -scale ${WxH}! \
-negate -threshold 0% -negate \
-type bilevel \
-define connected-components:verbose=true \
-connected-components 4 null: | grep "gray(0)" | awk '{print $2}'`)
num=${#cropArr[*]}
for ((i=0; i<num; i++)); do
j=$((i+1))
jj=`printf %02d $j`
convert 043-lg.jpg -crop "${cropArr[$i]}" +repage -bordercolor white -border 0 image_line_$jj.jpg
done

There is, however, 1 problem, which is hopefully very easy to solve...

The slices are all mixed up! I.e. to put the picture together again, I need to start with 06, then 04, then 03, 02, 01, 05. I don't even see a pattern here... Why doesn't it number my slices from top to bottom?

Re: Cut image in horizontal slices

Posted: 2019-06-12T14:06:23-07:00
by fmw42
-connected components list regions from largest to smallest. So you will need to filter on the bounding box Y coordinate to sort in top to bottom order.

Re: Cut image in horizontal slices

Posted: 2019-06-12T14:31:14-07:00
by godfried76
Thanks for your advice, fmw42!

How would this work? I'm totally new to ImageMagick (and to bash scripting for that matter ;) ) so sorry if this is a trivial question...

Re: Cut image in horizontal slices

Posted: 2019-06-12T15:45:21-07:00
by fmw42
Please do not post in two places.

Try this with the image you posted. Put it in a folder (I called it testing). In the future, I suggest you do not put spaces in file names. It just makes it harder to process. You must then put quotes about the name.

I make no guarantees that the blur value of 0x4 and the threshold of 1% will work for all images. So you may have adjust.

Code: Select all

cd
cd desktop/testing
infile="Image 002.jpg"
inname=`convert "$infile" -format "%t" info:`
WxH=`convert "$infile" -format "%wx%h" info:`
cropArr=(`convert "$infile" -blur 0x4 \
-scale 1x! -scale ${WxH}! \
-negate -threshold 1% -negate \
-type bilevel \
-define connected-components:verbose=true \
-define connected-components:mean-color=true \
-connected-components 4 null: | grep "gray(0)" | tr "x" "+" | awk '{print $2}'`)
num=${#cropArr[*]}
sort_list=`echo "${cropArr[*]}" | tr " " "\012" | sort -n -t "+" -k4,4`
cropArrSort=($sort_list)
for ((i=0; i<num; i++)); do
j=$((i+1))
jj=`printf %02d $j`
cropval=`echo "${cropArrSort[$i]}" | sed -n 's/^\([^+]*\)[+]\([^+]*\)[+]\([^+]*\)[+]\([^+]*\)$/\1x\2+\3+\4/p'`
convert "$infile" -crop $cropval +repage -bordercolor white -border 2 "${inname}_line_$jj.jpg"
done

Re: Cut image in horizontal slices

Posted: 2019-06-12T18:38:28-07:00
by fmw42
If you also want the script to append the first 3 items, then try

Code: Select all

cd
cd desktop/testing
infile="Image 002.jpg"
inname=`convert "$infile" -format "%t" info:`
WxH=`convert "$infile" -format "%wx%h" info:`
cropArr=(`convert "$infile" -blur 0x4 \
-scale 1x! -scale ${WxH}! \
-negate -threshold 1% -negate \
-type bilevel \
-define connected-components:verbose=true \
-define connected-components:mean-color=true \
-connected-components 4 null: | grep "gray(0)" | tr "x" "+" | awk '{print $2}'`)
num=${#cropArr[*]}
sort_list=`echo "${cropArr[*]}" | tr " " "\012" | sort -n -t "+" -k4,4`
cropArrSort=($sort_list)
for ((i=0; i<num; i++)); do
cropval=`echo "${cropArrSort[$i]}" | sed -n 's/^\([^+]*\)[+]\([^+]*\)[+]\([^+]*\)[+]\([^+]*\)$/\1x\2+\3+\4/p'`
convert "$infile" -crop $cropval +repage -bordercolor white -border 2 tmp$i.miff
done
for ((i=0; i<$((num-2)); i++)); do
ii=`printf %02d $i`
if [ $i -eq 0 ]; then
convert tmp0.miff tmp1.miff tmp2.miff -append "${inname}_line_$ii.jpg"
else
j=$((i+2))
convert tmp$j.miff "${inname}_line_$ii.jpg"
fi
done
rm -f tmp*.miff

Re: Cut image in horizontal slices

Posted: 2019-06-13T11:15:42-07:00
by godfried76
AMAZING!! You are THE BEST!! Thank you so much!!

If anyone else is reading this, I could just add I made some very minor adaptations to the script, indicated in bold.

#!/bin/bash


cd ~
cd Afbeeldingen
infile=$1
inname=`convert "$infile" -format "%t" info:`
WxH=`convert "$infile" -format "%wx%h" info:`
cropArr=(`convert "$infile" -blur 0x3 \
-scale 1x! -scale ${WxH}! \
-negate -threshold 0% -negate \
-type bilevel \
-define connected-components:verbose=true \
-define connected-components:mean-color=true \
-connected-components 4 null: | grep "gray(0)" | tr "x" "+" | awk '{print $2}'`)
num=${#cropArr[*]}
sort_list=`echo "${cropArr[*]}" | tr " " "\012" | sort -n -t "+" -k4,4`
cropArrSort=($sort_list)
for ((i=0; i<num; i++)); do
cropval=`echo "${cropArrSort[$i]}" | sed -n 's/^\([^+]*\)[+]\([^+]*\)[+]\([^+]*\)[+]\([^+]*\)$/\1x\2+\3+\4/p'`
convert "$infile" -crop $cropval +repage -bordercolor white -border 2 tmp$i.miff
done
for ((i=0; i<$((num-2)); i++)); do
ii=`printf %02d $i`
if [ $i -eq 0 ]; then
convert tmp0.miff tmp1.miff tmp2.miff -append "${inname}_line_$ii.jpg"
else
j=$((i+2))
convert tmp$j.miff "${inname}_line_$ii.jpg"
fi
done
rm -f tmp*.miff