# HG changeset patch # User Rik # Date 1516166062 28800 # Node ID 3ad53e4793fc7fef7b11ef37571e7a20a4b8d5dc # Parent 55f61915701b17e67c92b7597d33dc98ab5874ac rgb2gray: New function to convert RGB images to grayscale images. * scripts/image/rgb2gray.m: New function. * scripts/image/module.mk: Add function to build system. * NEWS: Announce function. * image.txi: Add DOCSTRING to manual. * ind2gray.m, rgb2hsv.m, rgb2ind.m: Replace references to rgb2ntsc in documentation with rgb2gray. diff -r 55f61915701b -r 3ad53e4793fc NEWS --- a/NEWS Tue Jan 16 17:21:47 2018 -0800 +++ b/NEWS Tue Jan 16 21:14:22 2018 -0800 @@ -239,6 +239,7 @@ openvar quad2d repelem + rgb2gray rticks thetaticks vecnorm diff -r 55f61915701b -r 3ad53e4793fc doc/interpreter/image.txi --- a/doc/interpreter/image.txi Tue Jan 16 17:21:47 2018 -0800 +++ b/doc/interpreter/image.txi Tue Jan 16 21:14:22 2018 -0800 @@ -258,6 +258,8 @@ @DOCSTRING(hsv2rgb) +@DOCSTRING(rgb2gray) + @DOCSTRING(rgb2ntsc) @DOCSTRING(ntsc2rgb) diff -r 55f61915701b -r 3ad53e4793fc scripts/image/ind2gray.m --- a/scripts/image/ind2gray.m Tue Jan 16 17:21:47 2018 -0800 +++ b/scripts/image/ind2gray.m Tue Jan 16 21:14:22 2018 -0800 @@ -30,7 +30,7 @@ ## ## Implementation Note: There are several ways of converting colors to ## grayscale intensities. This functions uses the luminance value obtained -## from @code{rgb2ntsc} which is @code{I = 0.299*R + 0.587*G + 0.114*B}. +## from @code{rgb2gray} which is @code{I = 0.299*R + 0.587*G + 0.114*B}. ## Other possibilities include the value component from @code{rgb2hsv} or ## using a single color channel from @code{ind2rgb}. ## @seealso{gray2ind, ind2rgb} diff -r 55f61915701b -r 3ad53e4793fc scripts/image/module.mk --- a/scripts/image/module.mk Tue Jan 16 17:21:47 2018 -0800 +++ b/scripts/image/module.mk Tue Jan 16 21:14:22 2018 -0800 @@ -54,6 +54,7 @@ %reldir%/rgb2hsv.m \ %reldir%/rgb2ind.m \ %reldir%/rgb2ntsc.m \ + %reldir%/rgb2gray.m \ %reldir%/rgbplot.m \ %reldir%/spinmap.m \ %reldir%/spring.m \ diff -r 55f61915701b -r 3ad53e4793fc scripts/image/rgb2gray.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/image/rgb2gray.m Tue Jan 16 21:14:22 2018 -0800 @@ -0,0 +1,146 @@ +## Copyright (C) 2018 Rik Wehbring +## +## This file is part of Octave. +## +## Octave is free software: you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {} {@var{I} =} rgb2gray (@var{rgb_img}) +## @deftypefnx {} {@var{gray_map} =} rgb2gray (@var{rgb_map}) +## Transform an image or colormap from red-green-blue (RGB) color space to +## a grayscale intensity image. +## +## The input may be of class uint8, uint16, single, or double. The output is +## of the same class as the input. +## +## Implementation Note: +## The grayscale intensity is calculated as +## +## @example +## @group +## @var{I} = 0.2989*@var{R} + 0.5870*@var{G} + 0.1140*@var{B} +## @end group +## @end example +## +## @noindent +## which corresponds to the luminance channel when RGB is translated to YIQ +## as documented in @url{http://en.wikipedia.org/wiki/YIQ}. +## @seealso{rgb2hsv, rgb2ind} +## @end deftypefn + +function I = rgb2gray (rgb) + + if (nargin != 1) + print_usage (); + endif + + [rgb, sz, is_im, is_nd] ... + = colorspace_conversion_input_check ("rgb2gray", "RGB", rgb); + + ## Reference matrix for transform from http://en.wikipedia.org/wiki/YIQ and + ## truncated to 4 significant figures. Matlab uses this matrix for their + ## conversion. + xform = [0.2989; 0.5870; 0.1140]; + + ## Note that if the input is of class single, we also return an image + ## of class single. This is Matlab incompatible by design, since + ## Matlab always returning class double, is a Matlab bug (see patch #8709) + I = rgb * xform; + + ## Restore size if necessary + if (is_im) + if (is_nd) + I = reshape (I, [sz(1), sz(2), sz(4)]); + else + I = reshape (I, sz(1:2)); + endif + endif + +endfunction + + +## Test pure RED, GREEN, BLUE colors +%!assert (rgb2gray ([1 0 0]), 0.2989) +%!assert (rgb2gray ([0 1 0]), 0.5870) +%!assert (rgb2gray ([0 0 1]), 0.1140) + +## test tolerance input checking on floats +%! assert (rgb2gray ([1.5 1 1]), 1.149, 1e-3); + +## Test ND input +%!test +%! rgb = rand (16, 16, 3, 5); +%! I = zeros (16, 16, 5); +%! for i = 1:5 +%! I(:,:,i) = rgb2gray (rgb(:,:,:,i)); +%! endfor +%! assert (rgb2gray (rgb), I); + +## Test output class and size for input images. +## Most of the tests only test for colormap input. + +%!test +%! I = rgb2gray (rand (10, 10, 3)); +%! assert (class (I), "double"); +%! assert (size (I), [10 10]); + +%!test +%! I = rgb2gray (rand (10, 10, 3, "single")); +%! assert (class (I), "single"); +%! assert (size (I), [10 10]); + +%!test +%! rgb = (rand (10, 10, 3) * 3 ) - 0.5; # values outside range [0 1] +%! I = rgb2gray (rgb); +%! assert (class (I), "double"); +%! assert (size (I), [10 10]); + +%!test +%! rgb = (rand (10, 10, 3, "single") * 3 ) - 0.5; # values outside range [0 1] +%! I = rgb2gray (rgb); +%! assert (class (I), "single"); +%! assert (size (I), [10 10]); + +%!test +%! I = rgb2gray (randi ([0 255], 10, 10, 3, "uint8")); +%! assert (class (I), "double"); +%! assert (size (I), [10 10]); + +%!test +%! I = rgb2gray (randi ([0 65535], 10, 10, 3, "uint16")); +%! assert (class (I), "double"); +%! assert (size (I), [10 10]); + +%!test +%! I = rgb2gray (randi ([-128 127], 10, 10, 3, "int8")); +%! assert (class (I), "double"); +%! assert (size (I), [10 10]); + +%!test +%! rgb_double = reshape ([1 0 0 0 0 1 0 0 0 0 1 0], [2 2 3]); +%! rgb_uint8 = reshape (uint8 ([255 0 0 0 0 255 0 0 0 0 255 0]), +%! [2 2 3]); +%! rgb_int16 = int16 (double (rgb_double * uint16 (65535)) - 32768); +%! expected = [.2989, .1140; .5870, 0.0]; +%! +%! assert (rgb2gray (rgb_double), expected); +%! assert (rgb2gray (rgb_uint8), expected); +%! assert (rgb2gray (single (rgb_double)), single (expected)); + +## Test input validation +%!error rgb2gray () +%!error rgb2gray (1,2) +%!error rgb2gray ({1}) +%!error rgb2gray (ones (2,2)) diff -r 55f61915701b -r 3ad53e4793fc scripts/image/rgb2hsv.m --- a/scripts/image/rgb2hsv.m Tue Jan 16 17:21:47 2018 -0800 +++ b/scripts/image/rgb2hsv.m Tue Jan 16 21:14:22 2018 -0800 @@ -31,7 +31,7 @@ ## ## Output class and size will be the same as input. ## -## @seealso{hsv2rgb, rgb2ind, rgb2ntsc} +## @seealso{hsv2rgb, rgb2ind, rgb2gray} ## @end deftypefn ## Author: Kai Habel diff -r 55f61915701b -r 3ad53e4793fc scripts/image/rgb2ind.m --- a/scripts/image/rgb2ind.m Tue Jan 16 17:21:47 2018 -0800 +++ b/scripts/image/rgb2ind.m Tue Jan 16 21:14:22 2018 -0800 @@ -37,7 +37,7 @@ ## supported, both via a single input (@var{rgb}) or its three color channels ## as separate variables. ## -## @seealso{ind2rgb, rgb2hsv, rgb2ntsc} +## @seealso{ind2rgb, rgb2hsv, rgb2gray} ## @end deftypefn ## FIXME: This function has a very different syntax than the Matlab