With command "convert" I know how to replace the color of a region having the coordinates and size, but is there a way to replace within an image, all regions that have for example 40 pixel in height? Thanks
This would be an example of input image where there 4 green rectangles with 40 pixels in height.
And this would be the output where those 4 green rectangles were replace to black knowing their height but not their coordinates, if possible.
I will try to help Mark get finished. I use ImageMagick and some unix code as follows with Imagemagick's Connected Components Labeling (-connected-components).
Here is the simple connect components results for all colors in your image:
convert in-1.png \
-define connected-components:verbose=true \
-connected-components 4 \
null:
Objects (id: bounding-box centroid area mean-color):
0: 256x256+0+0 133.6,134.1 50820 srgb(255,255,255)
1: 86x40+23+30 65.5,49.5 3440 srgb(0,127,70)
6: 60x40+42+126 71.5,145.5 2400 srgb(0,127,70)
4: 86x27+22+80 64.5,93.0 2322 srgb(0,38,255)
5: 86x27+121+121 163.5,134.0 2322 srgb(0,127,70)
2: 37x40+127+59 145.0,78.5 1480 srgb(0,127,70)
3: 36x40+177+59 194.5,78.5 1440 srgb(0,127,70)
7: 41x32+89+186 109.0,201.5 1312 srgb(255,106,0)
Note that none of your green, i.e, srgb(0,127,70) have heights above 40. All are 40 and one is 27. So to demonstrate, lets get all boxes greater than 30.
To the above code, I first select all the green objects, remove the leading space, extract the bounding box, which is field 2 and then change the x to a +.
Then I loop over each bounding box and extract the ht, and top left corner xx and yy values. I test the ht against the htval=30 and if it passes, I flood fill the green with black.
htval=30
convert in-1.png in-1_result.png
bboxArr=(`convert in-1.png \
-define connected-components:verbose=true \
-connected-components 4 \
null: | grep "srgb(0,127,70)" | sed 's/^[ ]*//' | cut -d\ -f2 | tr "x" "+"`)
num=${#bboxArr[*]}
for ((i=0; i<num; i++)); do
ht=`echo ${bboxArr[$i]} | cut -d+ -f2`
xx=`echo ${bboxArr[$i]} | cut -d+ -f3`
yy=`echo ${bboxArr[$i]} | cut -d+ -f4`
if [ $ht -gt $htval ]; then
convert in-1_result.png -fill black -draw "color $xx,$yy floodfill" -alpha off in-1_result.png
fi
done
Note in the above, the line
null: | grep "srgb(0,127,70)" | sed 's/^[ ]*//' | cut -d\ -f2 | tr "x" "+"`)
could be replaced with
null: | awk '/srgb\(0,127,70\)/ && sub(/x/, "+") {print $2}'
ADDITION:
Here is a more compact method using awk to do all the filtering and save the output as color x,y floodfill. Then only one draw command is needed to do the processing.
convert in-1.png in-1_result.png
floodfill_arr=(`convert in-1.png \
-define connected-components:verbose=true \
-connected-components 4 \
null: | awk '/srgb\(0,127,70\)/ && sub(/[x]/, "+") && split($2, arr, "+") {if (arr[4]>30) {print " color " arr[3] "," arr[4] " floodfill"}}'`)
echo "${floofill_arr[*]}"
color 42,126 floodfill color 121,121 floodfill color 127,59 floodfill color 177,59 floodfill
convert in-1_result.png -fill black -draw "${floodfill_arr[*]}" -alpha off in-1_result.png
The awk first finds all lines with the color green, then replaces any x
with +
, then splits field $2 into array (arr) parts using field separator +
, then tests if the 4th arr field (ht) is larger than 30 and if so, then prints the -draw command for each bounding box that passes the test.