Reputation: 2298
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.
Upvotes: 2
Views: 312
Reputation: 53154
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.
Upvotes: 2
Reputation: 207670
You can use ImageMagick's "Connected Component Analysis: to find all the blobs in your image like this:
convert blobs.png -define connected-components:verbose=true -connected-components 4 null:
Sample Output
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)
There is a header line that tells you what all the fields are and then one line per blob found, Disregard the first non-header line because it is the white background - see last field is srgb(255,255,255)
.
Look at the second-to-last line and it is 36 pixels wide by 40 pixels tall and has a mean colour of srgb(0,127,70)
. I guess that is a blob you want to fill-in or change colour.
If you want to find blobs that are 40 pixels tall, pass that through grep
like this:
convert blobs.png \
-define connected-components:verbose=true \
-connected-components 4 null: | grep "x40+"
and you'll get all the 40-high blobs:
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)
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)
I will add some more tomorrow if you can't see how to finish it off - it is late here.
Upvotes: 1