Page 1 of 1
Extracting pixels within a certain hue bracket
Posted: 2016-03-20T01:50:34-07:00
by skunkuncle
I would like to extract only pixels within a certain hue bracket - let's say within 15% of pure yellow - from an image.
My purpose is to separate post-its of different colors from a picture of a whiteboard.
Ideally it's shown here:
http://imgur.com/a/nXmkq
Where this
is the original image and these
http://imgur.com/NTOEsfA
http://imgur.com/qxmg9Wx
http://imgur.com/euyG7jd
are the separated ones - which I've obtained by using the color selector in GIMP
I've tried separating the image by hue like this
Code: Select all
convert whited.jpg -colorspace HSL -channel Hue -separate -fill white -draw "color 0,0 floodfill" hue.jpg
And then using levels as masks, but it always mixes up yellow and green post-its.
I'm comfortable with perl, so I am close to desperation - and converting the whole image, filtering in perl, and converting back. There surely must be a better way than that.
Thanks.
Re: Extracting pixels within a certain hue bracket
Posted: 2016-03-20T05:43:22-07:00
by snibgo
What image processing has already been done? Perhaps this was a photograph of a whiteboard. The lighting wasn't even, so the top was lighter than the bottom. This could be corrected, except that the background has been removed. Without that information, the job of separating the green from yellow postits is hard.
However, it isn't too bad. The yellow postits have the red channel values greater than the green channel values. The green postits have green channel greater than red channel. So subtracting these differentiates them. Windows BAT syntax.
Code: Select all
set SRC=0HDxdpj.jpg
%IM%convert ^
%SRC% ^
-channel RG ^
-separate ^
+channel ^
-compose Mathematics -define "compose:args=0,-1,1,0.5" ^
-composite ^
m.png
m.png is grayscale. The postits with gray > 50% are yellow. The postits darker than 50% are green or blue.
In fact, blue postits are 23% to 29%, and green are 40% to 47%. So this also distinguishes blue from green; threshold at say 35%.
Re: Extracting pixels within a certain hue bracket
Posted: 2016-03-20T06:14:48-07:00
by snibgo
Distinguishing by just a hue channel isn't so clear.
Code: Select all
%IM%convert ^
%SRC% ^
-colorspace HCL ^
-set colorspace sRGB ^
-channel R -separate +channel ^
h.png
h.png records hue on a grayscale. Yellow postits are 13% to 15%. Green postits are 18% to 26%. Blue postits are 58% to 59%. So they don't overlap, and could be thresholded at say 16% and 41%. But there is wide variation in the green postits, with only a small margin between yellow and green postits.
Re: Extracting pixels within a certain hue bracket
Posted: 2016-03-20T16:16:22-07:00
by skunkuncle
Thanks - following your hints and a bit of googling I ended up using the -fx option like this (unix syntax):
Code: Select all
convert "$1" -fuzz 15% -fill white -draw "color 0,0 floodfill" whited.jpg
convert whited.jpg -fx "(hue > 0.17 && hue < 0.28) && lightness < 0.9 ? black : white" \
-morphology Erode Octagon -morphology Dilate Octagon mask_green.jpg && \
composite mask_green.jpg whited.jpg -compose Screen out_green.jpg &
convert whited.jpg -fx "(hue > 0.53 && hue < 0.60) && lightness < 0.9 ? black : white" \
-morphology Erode Octagon -morphology Dilate Octagon mask_blue.jpg && \
composite mask_blue.jpg whited.jpg -compose Screen out_blue.jpg &
convert whited.jpg -fx "(hue > 0.09 && hue < 0.16) && lightness < 0.9 ? black : white" \
-morphology Erode Octagon -morphology Dilate Octagon mask_yellow.jpg && \
composite mask_yellow.jpg whited.jpg -compose Screen out_yellow.jpg &
It works OK, though it could stand some improvement.
Re: Extracting pixels within a certain hue bracket
Posted: 2016-03-20T18:52:44-07:00
by fmw42
convert whited.jpg -fx "(hue > 0.17 && hue < 0.28) && lightness < 0.9 ? black : white" \
-morphology Erode Octagon -morphology Dilate Octagon mask_green.jpg && \
composite mask_green.jpg whited.jpg -compose Screen out_green.jpg
NOTE you can make this one command by using the convert -compose syntax so you do not have to save the mask_green.jpg to disk, nor read the whited.jpg image twice.
Code: Select all
convert whited.jpg \
\( -clone 0 -fx "(hue > 0.17 && hue < 0.28) && lightness < 0.9 ? black : white" \
-morphology Erode Octagon -morphology Dilate Octagon \) \
-compose Screen -composite out_green.jpg
See
http://www.imagemagick.org/Usage/compose/#compose
Re: Extracting pixels within a certain hue bracket
Posted: 2016-03-20T21:15:40-07:00
by snibgo
skunkuncle wrote:It works OK, though it could stand some improvement.
You write intermediate results to JPG. JPG compression is lossy, which means it mangles pixels. As a rule of thumb, you should NEVER use JPG for intermediate results. Especially not when you a reducing images to flat colours, which JPG will mangle horribly.
Re: Extracting pixels within a certain hue bracket
Posted: 2016-03-21T00:12:21-07:00
by skunkuncle
Hi snibgo, hi fmw42 - thanks a lot!
I'd never used the "\(...\)" syntax - now I get it. Nice learning for me.
And yes, writing to JPG sucks, I shouldn't have! I'll fix it in the next version - today.
Thanks again to all.