From: <ha...@us...> - 2008-10-01 09:51:53
|
Revision: 5325 http://octave.svn.sourceforge.net/octave/?rev=5325&view=rev Author: hauberg Date: 2008-10-01 09:51:38 +0000 (Wed, 01 Oct 2008) Log Message: ----------- Remove imread and imwrite as they have been moved to Octave Modified Paths: -------------- trunk/octave-forge/main/image/DESCRIPTION trunk/octave-forge/main/image/src/Makeconf.in trunk/octave-forge/main/image/src/configure.base Removed Paths: ------------- trunk/octave-forge/main/image/inst/imread.m trunk/octave-forge/main/image/inst/imwrite.m trunk/octave-forge/main/image/src/__magick_read__.cc Modified: trunk/octave-forge/main/image/DESCRIPTION =================================================================== --- trunk/octave-forge/main/image/DESCRIPTION 2008-09-30 17:56:02 UTC (rev 5324) +++ trunk/octave-forge/main/image/DESCRIPTION 2008-10-01 09:51:38 UTC (rev 5325) @@ -5,15 +5,13 @@ Maintainer: The Octave Community Title: Image Processing Description: The Octave-forge Image package provides functions for - reading, writing, and processing images. The package supports - almost all image formats through the use of ImageMagick. + processing images. The package also provides functions for feature extraction, image statistics, spatial and geometric transformations, morphological operations, linear filtering, and much more. -Depends: octave (>= 2.9.10) +Depends: octave (>= 3.1.51) Autoload: yes BuildRequires: png-devel BuildRequires: jpeg-devel -SystemRequirements: ImageMagick License: GPL version 2 or later Url: http://octave.sf.net Deleted: trunk/octave-forge/main/image/inst/imread.m =================================================================== --- trunk/octave-forge/main/image/inst/imread.m 2008-09-30 17:56:02 UTC (rev 5324) +++ trunk/octave-forge/main/image/inst/imread.m 2008-10-01 09:51:38 UTC (rev 5325) @@ -1,170 +0,0 @@ -## Copyright (C) 2002 Andy Adler -## -## This program 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 2, or (at your option) -## any later version. USE THIS SOFTWARE AT YOUR OWN RISK. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{I} =} imread(@var{filename}) -## Read images from various file formats. -## -## The size and numeric class of the output depends on the -## format of the image. A colour image is returned as an -## MxNx3 matrix. Grey-level and black-and-white images are -## of size MxN. -## The colour depth of the image determines the numeric -## class of the output: 'uint8' or 'uint16' for grey -## and colour, and 'logical' for black and white. -## -## Note: For image formats other than jpeg and png, the -## ImageMagick "convert" and "identify" utilities -## are needed. ImageMagick can be found at www.imagemagick.org -## @end deftypefn - -## Author: Andy Adler -## -## Modified: Stefan van der Walt <st...@su...> -## Date: 24 January 2005 -## -## Modified: Thomas Weber <tho...@gm...> -## Date: 20 December 2006 -## Change parsing of imagemagick's output to get the 'color' depth for grayscale -## images -## -## Modified Kristian Rumberg <kri...@gm...> -## Date 2 April 2008 -## Imread now works with BMP's created with "convert inputimage out.bmp" -## (tested with stable release Octave 3.0 in GNU/Linux and Windows XP), -## modified the calling parameters to identify and convert - -function varargout = imread(filename, varargin) - if (nargin != 1) - usage("I = imread(filename)") - endif - - if !ischar (filename) - error("imread: filename must be a string") - endif - - filename = tilde_expand(filename); - fn = file_in_path(IMAGE_PATH, filename); - if isempty(fn) - error("imread: cannot find %s", filename); - endif - - - [ig, ig, ext] = fileparts(fn); - ext = upper(ext); - - ## divert jpegs and pngs to "jpgread" and "pngread" - if ( file_in_loadpath("jpgread.oct") && - (strcmp(ext, ".JPG") || strcmp(ext, ".JPEG")) ) - varargout{1} = jpgread(fn); - break - endif - if ( file_in_loadpath("pngread.oct") && (strcmp(ext, ".PNG")) ) - varargout{1} = pngread(fn); - break - endif - - ## alternately, use imagemagick - if ( file_in_loadpath("__magick_read__.oct") ) - [varargout{1:nargout}] = __magick_read__(fn, varargin{:}); - break - endif - - [sys, ident] = system(sprintf('identify -verbose \"%s\" | grep -e "bit" -e Type', fn)); - if (sys != 0) - error("imread: error running ImageMagick's 'identify' on %s", fn); - endif - depth = re_grab("([[:digit:]]{1,2})-bit", ident); - imtype = re_grab("Type: ([[:alpha:]]*)", ident); - - depth = str2num(depth); - if isempty(depth) || (pow2(nextpow2(depth)) != depth) - error("imread: invalid image depth %s", depth); - endif - - if !( strcmp(imtype, "Bilevel") || strcmp(imtype, "Grayscale") || - strcmp(imtype, "TrueColor") || strcmp(imtype, "TrueColorMatte") || - strcmp(imtype, "Palette") ) - error("imread: unknown image type '%s'", imtype); - endif - - switch (imtype) - case {"Bilevel"} - fmt = "pgm"; - case {"Grayscale"} - fmt = "pgm"; - case {"TrueColor", "TrueColorMatte", "Palette"} - fmt = "ppm"; - endswitch - - ## Why are pipes so slow? - ## cmd = sprintf("convert -flatten -strip %s %s:-", fn, fmt); - - tmpf = [tmpnam(), ".", fmt]; - ##cmd = sprintf("convert -flatten -strip +compress '%s' '%s' 2>/dev/null", - ## fn, tmpf); - cmd = sprintf("convert -strip \"%s\" \"%s\"", fn, tmpf); - - sys = system(cmd); - if (sys != 0) - error("imread: error running ImageMagick's 'convert'"); - unlink(tmpf); - endif - - try - fid = fopen(tmpf, "rb"); - catch - unlink(tmpf); - error("imread: could not open temporary file %s", tmpf) - end_try_catch - - fgetl(fid); # P5 or P6 (pgm or ppm) - [width, height] = sscanf(fgetl(fid), "%d %d", "C"); - fgetl(fid); # ignore max components - - if (depth == 16) - ## PGM format has MSB first, i.e. big endian - [data, count] = fread(fid, "uint16", 0, "ieee-be"); - else - [data, count] = fread(fid, "uint8"); - endif - - fclose(fid); - unlink(tmpf); - - if (any(strcmp(imtype, {"TrueColor", "TrueColorMatte", "Palette"}))) - channels = 3; - else - channels = 1; - endif - if (count != width*height*channels) - error("imread: image data chunk has invalid size %i != %i*%i*%i == %i", - count, width, height, channels, width*height*channels); - endif - - varargout = {}; - switch (imtype) - case {"Bilevel"} - varargout{1} = logical(reshape(data, width, height)'); - case {"Grayscale"} - varargout{1} = uint8(reshape(data, width, height)'); - case {"TrueColor", "TrueColorMatte", "Palette"} - varargout{1} = cat(3, reshape(data(1:3:end), width, height)', - reshape(data(2:3:end), width, height)', - reshape(data(3:3:end), width, height)'); - eval(sprintf("varargout{1} = uint%d(varargout{1});", depth)); - endswitch -endfunction - -function value = re_grab(re, str) - T = regexp(str,re,'tokens'); - if (isempty(T)) - value = ""; - else - value = T{1}{1}; - endif -endfunction Deleted: trunk/octave-forge/main/image/inst/imwrite.m =================================================================== --- trunk/octave-forge/main/image/inst/imwrite.m 2008-09-30 17:56:02 UTC (rev 5324) +++ trunk/octave-forge/main/image/inst/imwrite.m 2008-10-01 09:51:38 UTC (rev 5325) @@ -1,401 +0,0 @@ -## Copyright (C) 2002 Andy Adler -## -## This program 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 2, or (at your option) -## any later version. USE THIS SOFTWARE AT YOUR OWN RISK. - -## -*- texinfo -*- -## @deftypefn {Function File} imwrite(@var{fname}, @var{img}) -## Write image from octave to various file formats -## -## Note: this requires the ImageMagick "convert" utility. -## get this from www.imagemagick.org if required -## additional documentation of options is available from the -## convert man page. -## -## @deftypefnx{Function File} imwrite(@var{fname}, @var{img}) -## @var{img} is a greyscale (0-255) of image in fname. -## @deftypefnx{Function File} imwrite(@var{fname}, @var{img}, @var{map}) -## @var{map} is a matrix of [r,g,b], 0-1 triplesm and -## @var{img} is a matrix on indeces into map. -## @deftypefnx{Function File} imwrite(@var{fname}, @var{r}, @var{g}, @var{b}); -## @var{r}, @var{g}, @var{b} are red, green, blue (0-255) compondents. -## -## Formats for image fname -## @enumerate -## @item -## Simple guess from extention, i.e. "fig.jpg", "blah.gif". -## @item -## Specify explicitly, i.e. "jpg:fig.jpg", "gif:blah.gif". -## @item -## Specify subimage for multi-image format: "tiff:file.tif[3]". -## @item -## Raw images (row major format) specify geometry: "raw:img[256x180]". -## @end enumerate -## -## @deftypefnx{Function File} imwrite(@var{fname}, @var{img}, @var{options}) -## @deftypefnx{Function File} imwrite(@var{fname}, @var{img}, @var{map}, @var{options}) -## @deftypefnx{Function File} imwrite(@var{fname}, @var{r}, @var{g}, @var{b}, @var{options}); -## It is possible to give extra options to imwrite, for example: -## @example -## options= ["-rotate 25"; -## "-crop 200x200+150+150"; -## "-sample 200%" ]; -## @end example -## will rotate, crop, and then expand the image. -## note that the order of operations is important -## -## The following options are supported -## @table @code -## @item -antialias -## remove pixel-aliasing -## @item -background color -## background color -## @item -blur geometry -## blur the image -## @item -border geometry -## surround image with a border of color -## @item -bordercolor color -## border color -## @item -box color -## color for annotation bounding box -## @item -charcoal radius -## simulate a charcoal drawing -## @item -colorize value -## colorize the image with the fill color -## @item -colors value -## preferred number of colors in the image -## @item -colorspace type -## alternate image colorspace -## @item -comment string -## annotate image with comment -## @item -compress type -## type of image compression -## @item -contrast -## enhance or reduce the image contrast -## @item -crop geometry -## preferred size and location of the cropped image -## @item -density geometry -## vertical and horizontal density of the image -## @item -depth value -## depth of the image -## @item -despeckle -## reduce the speckles within an image -## @item -dispose method -## GIF disposal method -## @item -dither -## apply Floyd/Steinberg error diffusion to image -## @item -draw string -## annotate the image with a graphic primitive -## @item -edge radius -## apply a filter to detect edges in the image -## @item -emboss radius -## emboss an image -## @item -enhance -## apply a digital filter to enhance a noisy image -## @item -equalize -## perform histogram equalization to an image -## @item -fill color -## color to use when filling a graphic primitive -## @item -filter type -## use this filter when resizing an image -## @item -flip -## flip image in the vertical direction -## @item -flop -## flop image in the horizontal direction -## @item -font name -## font for rendering text -## @item -frame geometry -## surround image with an ornamental border -## @item -fuzz distance -## colors within this distance are considered equal -## @item -gamma value -## level of gamma correction -## @item -geometry geometry -## perferred size or location of the image -## @item -gaussian geometry -## gaussian blur an image -## @item -gravity type -## vertical and horizontal text placement -## @item -implode amount -## implode image pixels about the center -## @item -intent type -## Absolute, Perceptual, Relative, or Saturation -## @item -interlace type -## None, Line, Plane, or Partition -## @item -label name -## assign a label to an image -## @item -level value -## adjust the level of image contrast -## @item -list type -## Color, Delegate, Format, Magic, Module, or Type -## @item -map filename -## transform image colors to match this set of colors -## @item -matte -## store matte channel if the image has one -## @item -median radius -## apply a median filter to the image -## @item -modulate value -## vary the brightness, saturation, and hue -## @item -monochrome -## transform image to black and white -## @item -morph value -## morph an image sequence -## @item -negate -## replace every pixel with its complementary color -## @item -noise radius -## add or reduce noise in an image -## @item -normalize -## transform image to span the full range of colors -## @item -opaque color -## change this color to the fill color -## @item -page geometry -## size and location of an image canvas -## @item -paint radius -## simulate an oil painting -## @item -profile filename -## add ICM or IPTC information profile to image -## @item -quality value -## JPEG/MIFF/PNG compression level -## @item -raise value -## lighten/darken image edges to create a 3-D effect -## @item -region geometry -## apply options to a portion of the image -## @item -roll geometry -## roll an image vertically or horizontally -## @item -rotate degrees -## apply Paeth rotation to the image -## @item -sample geometry -## scale image with pixel sampling -## @item -scale geometry -## resize image -## @item -segment values -## segment an image -## @item -seed value -## pseudo-random number generator seed value -## @item -shade degrees -## shade the image using a distant light source -## @item -sharpen geometry -## sharpen the image -## @item -shave geometry -## shave pixels from the image edges -## @item -shear geometry -## slide one edge of the image along the X or Y axis -## @item -size geometry -## width and height of image -## @item -solarize threshold -## negate all pixels above the threshold level -## @item -spread amount -## displace image pixels by a random amount -## @item -stroke color -## color to use when stoking a graphic primitive -## @item -strokewidth value -## width of stroke -## @item -swirl degrees -## swirl image pixels about the center -## @item -texture filename -## name of texture to tile onto the image background -## @item -threshold value -## threshold the image -## @item -tile filename -## tile image when filling a graphic primitive -## @item -transparent color -## make this color transparent within the image -## @item -treedepth value -## depth of the color tree -## @item -type type -## image type -## @item -units type -## PixelsPerInch, PixelsPerCentimeter, or Undefined -## @item -unsharp geometry -## sharpen the image -## @end table -## @end deftypefn - -function imwrite(fname, p2, p3 ,p4 ,p5 ); - -try save_empty_list_elements_ok= empty_list_elements_ok; -catch save_empty_list_elements_ok= 0; -end -try save_warn_empty_list_elements= warn_empty_list_elements; -catch save_warn_empty_list_elements= 0; -end -unwind_protect -empty_list_elements_ok= 1; -warn_empty_list_elements= 0; - -# some older versions of octave didn't seem handle piped output correctly -usepipe=1; - -# Support matlabs input order -if (nargin >= 2 && ismatrix(fname) && ischar(p2)) - tmp = p2; - p2 = fname; - fname = tmp; -endif - -if ( nargin <= 1 ) || ... - ( ! ischar (fname)) || ... - ( nargin == 2 && ischar(p2) ) - usage([ ... - "imwrite( fname, img )\n", ... - "imwrite( fname, img, map )\n", ... - "imwrite( fname, r,g,b );\n", ... - "imwrite( fname, img, options )\n", ... - "imwrite( fname, img, map, options )\n", ... - "imwrite( fname, r,g,b, options );\n"]); -endif - -fname = tilde_expand(fname); - -# Put together the options string -# TODO: add some error checking to options -option_str=""; -n_mat= nargin-1; - -options= eval(sprintf("p%d",nargin)); -# process options strings if given -if ischar(options) - n_mat--; - for i= 1:size(options,1) - option_str=[option_str," ", options(i,:) ]; - end -elseif is_list( options ) - n_mat--; - for i= 1:length(options) - option_str=[option_str," ", nth(options,i) ]; - end -end - -[hig,wid] = size(p2); -if n_mat==1 - data= p2'; - outputtype="pgm"; - pnm_sig="P5"; -elseif n_mat==2 - img= p2'; - data= [ reshape(p3(img,1),1, hig*wid); - reshape(p3(img,2),1, hig*wid); - reshape(p3(img,3),1, hig*wid) ]; - outputtype="ppm"; - pnm_sig="P6"; -elseif n_mat==3 - data= [ reshape(p2',1, hig*wid); - reshape(p3',1, hig*wid); - reshape(p4',1, hig*wid) ]; - outputtype="ppm"; - pnm_sig="P6"; -else - error("imwrite: too many data matrices specified"); -end - -# Scale data depending on data type -switch(class(data)) -case "double" - data *= 255; -case "uint8" -case "uint16" - data /= 255; -otherwise - error("imwrite: unsupported data type %s", class(data)); -endswitch - -if strcmp([computer](9:13), "msdos") - _null = "null:"; - _apostroph = "\""; -else - _null = "/dev/null"; - _apostroph = "\""; -endif - -if usepipe - pname= sprintf("convert %s %s:- %c%s%c 2> %s", - option_str, outputtype, _apostroph, fname, _apostroph, _null); - fid= popen(pname ,'w'); - - if fid<0; - error('could not create image data. Is ImageMagick installed?'); - end -else - tnam= tmpnam(); - cmd= sprintf("convert %s %c%s:%s%c %c%s%c 2> %s", - option_str, _apostroph, outputtype, tnam, _apostroph, _apostroph, fname, _apostroph, _null); - fid= fopen(tnam, "wb"); -end - - fprintf(fid,"%s\n%d %d\n255\n",pnm_sig,wid,hig); - write_count= fwrite(fid,data(:)); - if write_count != prod(size(data)) - fclose(fid); - if ~usepipe - unlink(tnam); - end - error(['Problem writing image: ', fname ]); - end - - fclose(fid); - if ~usepipe - retcode = system(cmd); - if retcode !=0 - error('could not call imagemagick convert'); - end - unlink( tnam ); - end - -unwind_protect_cleanup -empty_list_elements_ok= save_empty_list_elements_ok; -warn_empty_list_elements= save_warn_empty_list_elements; -end_unwind_protect - -# -# $Log$ -# -# Patch 2008/03/25 20:42:00 Michal Fita -# Compability with ImageMagick on Windows -# -# Revision 1.3 2007/01/02 21:58:38 hauberg -# Documentation is now in Texinfo (looks better on the website) -# -# Revision 1.2 2006/11/26 10:47:39 hauberg -# Compatibility changes -# -# Revision 1.1 2006/08/20 12:59:34 hauberg -# Changed the structure to match the package system -# -# Revision 1.11 2006/03/22 17:50:47 qspencer -# Change calls to 'system' function to reflect new ordering of output arguments. -# -# Revision 1.10 2005/09/08 02:00:17 pkienzle -# [for Bill Denney] isstr -> ischar -# -# Revision 1.9 2005/07/21 16:03:02 aadler -# Improve error messages and use pipes -# -# Revision 1.8 2005/05/25 03:43:40 pkienzle -# Author/Copyright consistency -# -# Revision 1.7 2005/04/25 01:05:28 aadler -# added GPL copyrights -# -# Revision 1.6 2003/09/12 14:22:42 adb014 -# Changes to allow use with latest CVS of octave (do_fortran_indexing, etc) -# -# Revision 1.5 2003/07/25 19:11:41 pkienzle -# Make sure all files names referenced in system calls are wrapped in quotes -# to protect against spaces in the path. -# -# Revision 1.4 2002/11/27 08:40:11 pkienzle -# author/license updates -# -# Revision 1.3 2002/03/19 18:14:13 aadler -# unfortunately using popen seems to create problems, mostly -# on win32, but also on linux, so we need to move to a tmpfile approach -# -# Revision 1.2 2002/03/17 05:26:14 aadler -# now accept filenames with spaces -# -# Revision 1.1 2002/03/11 01:56:47 aadler -# general image read/write functionality using imagemagick utilities -# -# Modified: trunk/octave-forge/main/image/src/Makeconf.in =================================================================== --- trunk/octave-forge/main/image/src/Makeconf.in 2008-09-30 17:56:02 UTC (rev 5324) +++ trunk/octave-forge/main/image/src/Makeconf.in 2008-10-01 09:51:38 UTC (rev 5325) @@ -6,7 +6,6 @@ @DEFHAVE_JPEG@ @DEFHAVE_PNG@ -@DEFHAVE_MAGICKXX@ MKOCTFILE=@MKOCTFILE@ %.o: %.c ; $(MKOCTFILE) -c $< Deleted: trunk/octave-forge/main/image/src/__magick_read__.cc =================================================================== --- trunk/octave-forge/main/image/src/__magick_read__.cc 2008-09-30 17:56:02 UTC (rev 5324) +++ trunk/octave-forge/main/image/src/__magick_read__.cc 2008-10-01 09:51:38 UTC (rev 5325) @@ -1,314 +0,0 @@ -#include <octave/oct.h> -#include <Magick++.h> -#include <iostream> -using namespace std; -using namespace Magick; - -unsigned int scaleQuantumToDepth (const Quantum &_quantum, unsigned int depth) -{ - return (static_cast<unsigned int> (static_cast<double>(_quantum) / - QuantumRange * ((1 << depth) - 1))); -} - -octave_value_list read_indexed_images(vector<Image> imvec, Array<int> frameidx, bool wantalpha) -{ - octave_value_list output; - int rows = imvec[0].baseRows(); - int columns = imvec[0].baseColumns(); - int nframes = frameidx.length(); - ImageType type = imvec[0].type(); - - unsigned int mapsize = imvec[0].colorMapSize(); - int i = mapsize; - unsigned int depth = 0; - while(i >>= 1) depth++; - i = 0; - depth--; - while(depth >>= 1) i++; - depth = 1 << i; - - int x, y, frame; - const IndexPacket *pix; - switch(depth) { - case 1: - case 2: - case 4: - case 8: - { - uint8NDArray im = uint8NDArray(dim_vector(rows, columns, nframes)); - for(frame=0; frame < nframes; frame++) { - imvec[frameidx(frame)].getConstPixels(0,0, columns, rows); - pix = imvec[frameidx(frame)].getConstIndexes(); - i = 0; - for(y=0; y < rows; y++) { - for(x=0; x < columns; x++) { - im(y, x, frame) = static_cast<octave_uint8>(pix[i++]); - } - } - } - im.chop_trailing_singletons(); - output(0) = octave_value(im); - } - break; - case 16: - { - uint16NDArray im = uint16NDArray(dim_vector(rows, columns, nframes)); - for(frame=0; frame < nframes; frame++) { - imvec[frameidx(frame)].getConstPixels(0,0, columns, rows); - pix = imvec[frameidx(frame)].getConstIndexes(); - i = 0; - for(y=0; y < rows; y++) { - for(x=0; x < columns; x++) { - im(y, x, frame) = static_cast<octave_uint16>(pix[i++]); - } - } - } - im.chop_trailing_singletons(); - output(0) = octave_value(im); - } - break; - default: - error("Index depths bigger than 16-bit not supported"); - return octave_value_list(); - } - - ColorRGB c; - Matrix map = Matrix(mapsize, 3); - Matrix alpha; - switch(type) { - case PaletteMatteType: -/* warning("palettematte"); - map = Matrix(mapsize, 3); - alpha = Matrix(mapsize, 1); - for(i = 0; i < mapsize; i++) { - warning("%d", i); - c = imvec[0].colorMap(i); - map(i, 0) = c.red(); - map(i, 1) = c.green(); - map(i, 2) = c.blue(); - alpha(i, 1) = c.alpha(); - } - break; */ - case PaletteType: - alpha = Matrix(0,0); - for(i = 0; i < mapsize; i++) { - c = imvec[0].colorMap(i); - map(i, 0) = c.red(); - map(i, 1) = c.green(); - map(i, 2) = c.blue(); - } - break; - default: - error("Unsupported indexed image type"); - return octave_value_list(); - } - - output(1) = octave_value(map); - if(wantalpha) { - output(2) = octave_value(alpha); - } - return output; -} - -template <class T> -octave_value_list read_images(vector<Image> imvec, Array<int> frameidx, - unsigned int depth) -{ - int i; - T im; - int rows = imvec[0].baseRows(); - int columns = imvec[0].baseColumns(); - int nframes = frameidx.length(); - ImageType type = imvec[0].type(); - int x, y, frame; - const PixelPacket *pix; - dim_vector idim = dim_vector(); - idim.resize(4); - idim(0) = rows; - idim(1) = columns; - idim(2) = 1; - idim(3) = nframes; - Array<int> idx(dim_vector(4)); - switch(type) { - case BilevelType: - // break; - case GrayscaleType: - im = T(dim_vector(rows, columns, nframes)); - for(frame=0; frame < nframes; frame++) { - pix = imvec[frameidx(frame)].getConstPixels(0,0, columns, rows); - i = 0; - for(y=0; y < rows; y++) { - for(x=0; x < columns; x++) { - im(y, x, frame) = scaleQuantumToDepth (pix[i++].red, depth); - } - } - } - break; - case GrayscaleMatteType: - idim(2) = 2; - im = T(idim); - for(frame=0; frame < nframes; frame++) { - idx(3) = frame; - i = 0; - pix = imvec[frameidx(frame)].getConstPixels(0,0, columns, rows); - for(y=0; y < rows; y++) { - idx(0) = y; - for(x=0; x < columns; x++) { - idx(1) = x; - idx(2) = 0; - im(idx) = scaleQuantumToDepth (pix[i].red, depth); - idx(2) = 1; - im(idx) = scaleQuantumToDepth (pix[i].opacity, depth); - i++; - } - } - } - break; - case PaletteType: - case TrueColorType: - idim(2) = 3; - im = T(idim); - for(frame=0; frame < nframes; frame++) { - idx(3) = frame; - i = 0; - pix = imvec[frameidx(frame)].getConstPixels(0,0, columns, rows); - for(y=0; y < rows; y++) { - idx(0) = y; - for(x=0; x < columns; x++) { - idx(1) = x; - idx(2) = 0; - im(idx) = scaleQuantumToDepth (pix[i].red, depth); - idx(2) = 1; - im(idx) = scaleQuantumToDepth (pix[i].green, depth); - idx(2) = 2; - im(idx) = scaleQuantumToDepth (pix[i].blue, depth); - i++; - } - } - } - break; - case PaletteMatteType: - case TrueColorMatteType: - case ColorSeparationType: - idim(2) = 4; - im = T(idim); - for(frame=0; frame < nframes; frame++) { - idx(3) = frame; - i = 0; - pix = imvec[frameidx(frame)].getConstPixels(0,0, columns, rows); - for(y=0; y < rows; y++) { - idx(0) = y; - for(x=0; x < columns; x++) { - idx(1) = x; - idx(2) = 0; - im(idx) = scaleQuantumToDepth (pix[i].red, depth); - idx(2) = 1; - im(idx) = scaleQuantumToDepth (pix[i].green, depth); - idx(2) = 2; - im(idx) = scaleQuantumToDepth (pix[i].blue, depth); - idx(2) = 3; - im(idx) = scaleQuantumToDepth (pix[i].opacity, depth); - i++; - } - } - } - break; - default: - error("Undefined Imagemagick image type"); - return octave_value_list(); - } - - im.chop_trailing_singletons(); - return octave_value_list(octave_value(im)); -} - -// instantiate templates -template octave_value_list read_images<boolNDArray>(vector<Image>, Array<int>, - unsigned int depth); -template octave_value_list read_images<uint8NDArray>(vector<Image>, - Array<int>, - unsigned int depth); -template octave_value_list read_images<uint16NDArray>(vector<Image>, - Array<int>, - unsigned int depth); - -DEFUN_DLD(__magick_read__, args, nargout, "\ --*- texinfo -*-\n\ -@deftypefn {Function File} {@var{m} =} __imagemagick_read__(@var{fname}, @var{index})\n\ -@deftypefnx{Function File} {[@var{m}, @var{colormap}] =} __imagemagick_read__(@var{fname}, @var{index})\n\ -@deftypefnx{Function File} {[@var{m}, @var{colormap}, @var{alpha}] =} __imagemagick_read__(@var{fname}, @var{index})\n\ -Read images with ImageMagick++. In general you should not be using this function.\n\ -Instead you should use @code{imread}.\n\ -@seealso{imread}\n\ -@end deftypefn\n\ -") { - octave_value_list output; - int i; - if(args.length() > 2 || args.length() < 1 || !args(0).is_string() \ - || nargout > 3) { - print_usage (); - return octave_value_list(); - } - Array<int> frameidx; - if(args.length() == 2 && args(1).is_real_type()) { - frameidx = args(1).int_vector_value(); - } else { - frameidx = Array<int>(1); - frameidx(0) = 1; - } - - vector<Image> imvec; - try { - // Read a file into vector of image objects - readImages(&imvec, args(0).string_value()); - } - catch( Warning &warning_ ) { - warning("Magick++ warning: %s", warning_.what()); - } - catch( ErrorCoder &error_) { - warning("Magick++ coder error: %s", error_.what()); - } - catch( Exception &error_ ) { - error("Magick++ exception: %s", error_.what()); - imvec.clear(); - return octave_value_list(); - } - - int nframes = imvec.size(); - for(i = 0; i < frameidx.length(); i++) { - frameidx(i) = frameidx(i) - 1; - if(frameidx(i) >= nframes || frameidx(i) < 0) { - error("Invalid index vector"); - imvec.clear(); - return output; - } - } - - ClassType klass = imvec[0].classType(); - if(klass == PseudoClass && nargout > 1) { - output = read_indexed_images(imvec, frameidx, (nargout == 3)); - } else { - unsigned int depth = imvec[0].modulusDepth(); - i = 0; - while(depth >>= 1) i++; - depth = 1 << i; - - if (depth == 1) - output = read_images<boolNDArray>(imvec, frameidx, depth); - else if (depth > 1 && depth <= 8) - output = read_images<uint8NDArray>(imvec, frameidx, depth); - else if (depth > 8 && depth <= 16) - output = read_images<uint16NDArray>(imvec, frameidx, depth); - else - error("Image depths bigger than 16-bit not supported"); - - if(nargout > 1) { - output(1) = Matrix(0,0); - if(nargout > 2) - output(2) = Matrix(0,0); - } - } - imvec.clear(); - - return output; -} Modified: trunk/octave-forge/main/image/src/configure.base =================================================================== --- trunk/octave-forge/main/image/src/configure.base 2008-09-30 17:56:02 UTC (rev 5324) +++ trunk/octave-forge/main/image/src/configure.base 2008-10-01 09:51:38 UTC (rev 5325) @@ -61,13 +61,4 @@ IMAGESTATUS="$IMAGESTATUS, png.h not found" fi -AC_CHECK_PROG(HAVE_MAGICKXX, Magick++-config, yes) -if test $HAVE_MAGICKXX ; then - IMAGESTATUS="$IMAGESTATUS, ImageMagick++" - AC_SUBST(DEFHAVE_MAGICKXX) - DEFHAVE_MAGICKXX="HAVE_MAGICKXX=1" -else - IMAGESTATUS="$IMAGESTATUS, ImageMagick++ not found" -fi - CONFIGURE_OUTPUTS="Makeconf" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ha...@us...> - 2008-10-05 19:21:07
|
Revision: 5334 http://octave.svn.sourceforge.net/octave/?rev=5334&view=rev Author: hauberg Date: 2008-10-05 19:18:25 +0000 (Sun, 05 Oct 2008) Log Message: ----------- Support a new set of spatial filters Modified Paths: -------------- trunk/octave-forge/main/image/INDEX trunk/octave-forge/main/image/inst/cordflt2.m trunk/octave-forge/main/image/inst/ordfilt2.m trunk/octave-forge/main/image/inst/ordfiltn.m trunk/octave-forge/main/image/src/Makefile Added Paths: ----------- trunk/octave-forge/main/image/inst/entropy.m trunk/octave-forge/main/image/inst/entropyfilt.m trunk/octave-forge/main/image/inst/rangefilt.m trunk/octave-forge/main/image/inst/stdfilt.m trunk/octave-forge/main/image/src/__spatial_filtering__.cc Removed Paths: ------------- trunk/octave-forge/main/image/src/__cordfltn__.cc Modified: trunk/octave-forge/main/image/INDEX =================================================================== --- trunk/octave-forge/main/image/INDEX 2008-10-03 14:13:36 UTC (rev 5333) +++ trunk/octave-forge/main/image/INDEX 2008-10-05 19:18:25 UTC (rev 5334) @@ -28,6 +28,7 @@ imhist mean2 std2 + entropy qtdecomp qtgetblk qtsetblk @@ -118,3 +119,6 @@ nlfilter im2col col2im + rangefilt + stdfilt + entropyfilt Modified: trunk/octave-forge/main/image/inst/cordflt2.m =================================================================== --- trunk/octave-forge/main/image/inst/cordflt2.m 2008-10-03 14:13:36 UTC (rev 5333) +++ trunk/octave-forge/main/image/inst/cordflt2.m 2008-10-05 19:18:25 UTC (rev 5334) @@ -20,8 +20,9 @@ ## @seealso{ordfilt2} ## @end deftypefn -function varargout = cordflt2(varargin) +function retval = cordflt2(A, nth, domain, S) warning(["cordflt2: this function is deprecated and will be removed in upcoming " "releases. Use 'ordfilt2' instead."]); - [varargout{1:nargout}] = __cordfltn__(varargin{:}); + + retval = __spatial_filtering__ (A, domain, "ordered", S, nth); endfunction Added: trunk/octave-forge/main/image/inst/entropy.m =================================================================== --- trunk/octave-forge/main/image/inst/entropy.m (rev 0) +++ trunk/octave-forge/main/image/inst/entropy.m 2008-10-05 19:18:25 UTC (rev 5334) @@ -0,0 +1,67 @@ +## Copyright (C) 2008 Søren Hauberg +## +## This program 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. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{E} =} entropy (@var{im}) +## @deftypefnx{Function File} {@var{E} =} entropy (@var{im}, @var{nbins}) +## Computes the entropy of an image. +## +## The entropy of the elements of the image @var{im} is computed as +## +## @example +## @var{E} = -sum (@var{P} .* log2 (@var{P}) +## @end example +## +## where @var{P} is the distribution of the elements of @var{im}. The distribution +## is approximated using a histogram with @var{nbins} cells. If @var{im} is +## @code{logical} then two cells are used by default. For other classes 256 cells +## are used by default. +## +## When the entropy is computed, zero-valued cells of the histogram are ignored. +## +## @seealso{entropyfilt} +## @end deftypefn + +function retval = entropy (I, nbins = 0) + ## Check input + if (nargin == 0) + error ("entropy: not enough input arguments"); + endif + + if (!ismatrix (I)) + error ("entropy: first input must be a matrix"); + endif + + if (!isscalar (nbins)) + error ("entropy: second input argument must be a scalar"); + endif + + ## Get number of histogram bins + if (nbins <= 0) + if (islogical (I)) + nbins = 2; + else + nbins = 256; + endif + endif + + ## Compute histogram + P = hist (I (:), nbins, true); + + ## Compute entropy (ignoring zero-entries of the histogram) + P += (P == 0); + retval = -sum (P .* log2 (P)); +endfunction Added: trunk/octave-forge/main/image/inst/entropyfilt.m =================================================================== --- trunk/octave-forge/main/image/inst/entropyfilt.m (rev 0) +++ trunk/octave-forge/main/image/inst/entropyfilt.m 2008-10-05 19:18:25 UTC (rev 5334) @@ -0,0 +1,100 @@ +## Copyright (C) 2008 Søren Hauberg +## +## This program 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. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{E} =} entropyfilt (@var{im}) +## @deftypefnx{Function File} {@var{E} =} entropyfilt (@var{im}, @var{domain}) +## @deftypefnx{Function File} {@var{E} =} entropyfilt (@var{im}, @var{domain}, @var{padding}, ...) +## Computes the local entropy in a neighbourhood around each pixel in an image. +## +## The entropy of the elements of the neighbourhood is computed as +## +## @example +## @var{E} = -sum (@var{P} .* log2 (@var{P}) +## @end example +## +## where @var{P} is the distribution of the elements of @var{im}. The distribution +## is approximated using a histogram with @var{nbins} cells. If @var{im} is +## @code{logical} then two cells are used. For other classes 256 cells +## are used. +## +## When the entropy is computed, zero-valued cells of the histogram are ignored. +## +## The neighbourhood is defined by the @var{domain} binary mask. Elements of the +## mask with a non-zero value are considered part of the neighbourhood. By default +## a 9 by 9 matrix containing only non-zero values is used. +## +## At the border of the image, extrapolation is used. By default symmetric +## extrapolation is used, but any method supported by the @code{padarray} function +## can be used. Since extrapolation is used, one can expect a lower entropy near +## the image border. +## +## @seealso{entropy, paddarray, stdfilt} +## @end deftypefn + +function retval = entropyfilt (I, domain = true (9), padding = "symmetric", varargin) + ## Check input + if (nargin == 0) + error ("entropyfilt: not enough input arguments"); + endif + + if (!ismatrix (I)) + error ("entropyfilt: first input must be a matrix"); + endif + + if (!ismatrix (domain)) + error ("entropyfilt: second input argument must be a logical matrix"); + endif + domain = (domain > 0); + + ## Get number of histogram bins + if (islogical (I)) + nbins = 2; + else + nbins = 256; + endif + + ## Convert to 8 or 16 bit integers if needed + switch (class (I)) + case {"double", "single", "int16", "int32", "int64", "uint16", "uint32", "uint64"} + min_val = double (min (I (:))); + max_val = double (max (I (:))); + if (min_val == max_val) + retval = zeros (size (I)); + return; + endif + I = (double (I) - min_val)./(max_val - min_val); + I = uint8 (255 * I); + case {"logical", "int8", "uint8"} + ## Do nothing + otherwise + error ("entropyfilt: cannot handle images of class '%s'", class (I)); + endswitch + size (I) + ## Pad image + pad = floor (size (domain)/2); + I = padarray (I, pad, padding, varargin {:}); + even = (round (size (domain)/2) == size (domain)/2); + idx = cell (1, ndims (I)); + for k = 1:ndims (I) + idx {k} = (even (k)+1):size (I, k); + endfor + I = I (idx {:}); + size (I) + ## Perform filtering + retval = __spatial_filtering__ (I, domain, "entropy", I, nbins); + +endfunction Modified: trunk/octave-forge/main/image/inst/ordfilt2.m =================================================================== --- trunk/octave-forge/main/image/inst/ordfilt2.m 2008-10-03 14:13:36 UTC (rev 5333) +++ trunk/octave-forge/main/image/inst/ordfilt2.m 2008-10-05 19:18:25 UTC (rev 5334) @@ -63,6 +63,6 @@ endif; A = impad(A, xpad, ypad, padding); -retval = __cordfltn__(A, nth, domain, S); +retval = __spatial_filtering__ (A, domain, "ordered", S, nth); endfunction Modified: trunk/octave-forge/main/image/inst/ordfiltn.m =================================================================== --- trunk/octave-forge/main/image/inst/ordfiltn.m 2008-10-03 14:13:36 UTC (rev 5333) +++ trunk/octave-forge/main/image/inst/ordfiltn.m 2008-10-05 19:18:25 UTC (rev 5334) @@ -95,5 +95,5 @@ A = A(idx{:}); ## Perform the filtering - retval = __cordfltn__(A, nth, domain, S); + retval = __spatial_filtering__ (A, domain, "ordered", S, nth); endfunction Added: trunk/octave-forge/main/image/inst/rangefilt.m =================================================================== --- trunk/octave-forge/main/image/inst/rangefilt.m (rev 0) +++ trunk/octave-forge/main/image/inst/rangefilt.m 2008-10-05 19:18:25 UTC (rev 5334) @@ -0,0 +1,71 @@ +## Copyright (C) 2008 Søren Hauberg +## +## This program 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. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{R} =} rangefilt (@var{im}) +## @deftypefnx{Function File} {@var{R} =} rangefilt (@var{im}, @var{domain}) +## @deftypefnx{Function File} {@var{R} =} rangefilt (@var{im}, @var{domain}, @var{padding}, ...) +## Computes the local intensity range in a neighbourhood around each pixel in +## an image. +## +## The intensity range of the pixels of a neighbourhood is computed as +## +## @example +## @var{R} = max (@var{x}) - min (@var{x}) +## @end example +## +## where @var{x} is the value of the pixels in the neighbourhood, +## +## The neighbourhood is defined by the @var{domain} binary mask. Elements of the +## mask with a non-zero value are considered part of the neighbourhood. By default +## a 3 by 3 matrix containing only non-zero values is used. +## +## At the border of the image, extrapolation is used. By default symmetric +## extrapolation is used, but any method supported by the @code{padarray} function +## can be used. +## +## @seealso{paddarray, entropyfilt, stdfilt} +## @end deftypefn + +function retval = rangefilt (I, domain = true (3), padding = "symmetric", varargin) + ## Check input + if (nargin == 0) + error ("rangefilt: not enough input arguments"); + endif + + if (!ismatrix (I)) + error ("rangefilt: first input must be a matrix"); + endif + + if (!ismatrix (domain)) + error ("rangefilt: second input argument must be a logical matrix"); + endif + domain = (domain > 0); + + ## Pad image + pad = floor (size (domain)/2); + I = padarray (I, pad, padding, varargin {:}); + even = (round (size (domain)/2) == size (domain)/2); + idx = cell (1, ndims (I)); + for k = 1:ndims (I) + idx {k} = (even (k)+1):size (I, k); + endfor + I = I (idx {:}); + + ## Perform filtering + retval = __spatial_filtering__ (I, domain, "range", I, 0); + +endfunction Added: trunk/octave-forge/main/image/inst/stdfilt.m =================================================================== --- trunk/octave-forge/main/image/inst/stdfilt.m (rev 0) +++ trunk/octave-forge/main/image/inst/stdfilt.m 2008-10-05 19:18:25 UTC (rev 5334) @@ -0,0 +1,74 @@ +## Copyright (C) 2008 Søren Hauberg +## +## This program 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. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{S} =} stdfilt (@var{im}) +## @deftypefnx{Function File} {@var{S} =} stdfilt (@var{im}, @var{domain}) +## @deftypefnx{Function File} {@var{S} =} stdfilt (@var{im}, @var{domain}, @var{padding}, ...) +## Computes the local standard deviation in a neighbourhood around each pixel in +## an image. +## +## The standard deviation of the pixels of a neighbourhood is computed as +## +## @example +## @var{S} = sqrt ((sum (@var{x} - @var{mu}).^2)/(@var{N}-1)) +## @end example +## +## where @var{mu} is the mean value of the pixels in the neighbourhood, +## @var{N} is the number of pixels in the neighbourhood. So, an unbiased estimator +## is used. +## +## The neighbourhood is defined by the @var{domain} binary mask. Elements of the +## mask with a non-zero value are considered part of the neighbourhood. By default +## a 3 by 3 matrix containing only non-zero values is used. +## +## At the border of the image, extrapolation is used. By default symmetric +## extrapolation is used, but any method supported by the @code{padarray} function +## can be used. Since extrapolation is used, one can expect a lower deviation near +## the image border. +## +## @seealso{std2, paddarray, entropyfilt} +## @end deftypefn + +function retval = stdfilt (I, domain = true (3), padding = "symmetric", varargin) + ## Check input + if (nargin == 0) + error ("stdfilt: not enough input arguments"); + endif + + if (!ismatrix (I)) + error ("stdfilt: first input must be a matrix"); + endif + + if (!ismatrix (domain)) + error ("stdfilt: second input argument must be a logical matrix"); + endif + domain = (domain > 0); + + ## Pad image + pad = floor (size (domain)/2); + I = padarray (I, pad, padding, varargin {:}); + even = (round (size (domain)/2) == size (domain)/2); + idx = cell (1, ndims (I)); + for k = 1:ndims (I) + idx {k} = (even (k)+1):size (I, k); + endfor + I = I (idx {:}); + + ## Perform filtering + retval = __spatial_filtering__ (I, domain, "std", I, 0); + +endfunction Modified: trunk/octave-forge/main/image/src/Makefile =================================================================== --- trunk/octave-forge/main/image/src/Makefile 2008-10-03 14:13:36 UTC (rev 5333) +++ trunk/octave-forge/main/image/src/Makefile 2008-10-05 19:18:25 UTC (rev 5334) @@ -8,14 +8,10 @@ PNG=pngread.oct pngwrite.oct endif -ifdef HAVE_MAGICKXX - IMAGEMAGICK=__magick_read__.oct -endif - -all: __cordfltn__.oct __bilateral__.oct __custom_gaussian_smoothing__.oct \ +all: __spatial_filtering__.oct __bilateral__.oct __custom_gaussian_smoothing__.oct \ bwlabel.oct bwfill.oct rotate_scale.oct hough_line.oct \ graycomatrix.oct deriche.oct __bwdist.oct nonmax_supress.oct \ - $(JPEG) $(PNG) $(IMAGEMAGICK) + $(JPEG) $(PNG) jpgread.oct: jpgread.cc $(MKOCTFILE) $< -ljpeg @@ -29,7 +25,4 @@ pngwrite.oct: pngwrite.cc $(MKOCTFILE) $< -lpng -__magick_read__.oct: __magick_read__.cc - $(MKOCTFILE) $< `Magick++-config --cppflags` `Magick++-config --ldflags` - clean: ; -$(RM) *.o octave-core core *.oct *~ Deleted: trunk/octave-forge/main/image/src/__cordfltn__.cc =================================================================== --- trunk/octave-forge/main/image/src/__cordfltn__.cc 2008-10-03 14:13:36 UTC (rev 5333) +++ trunk/octave-forge/main/image/src/__cordfltn__.cc 2008-10-05 19:18:25 UTC (rev 5334) @@ -1,289 +0,0 @@ -// Copyright (C) 2008 Soren Hauberg -// -// This program 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. -// -// This program 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 this program; if not, see <http://www.gnu.org/licenses/>. - -// The 'compare' and 'selnth' functions are copied from the 'cordflt2' function -// developed by Teemu Ikonen. This work was released under GPLv2 or later. -// -- Soren Hauberg, March 21st, 2008 - -#include <octave/oct.h> - -// Template function for comparison -// ET is the type of the matrix element -template <class ET> -inline bool compare (const ET a, const ET b) -{ - if (a > b) - return 1; - else - return 0; -} - -// Explicit template function for complex compare -template <> inline bool compare<Complex> (const Complex a, const Complex b) -{ - const double anorm2 = a.real () * a.real () + a.imag () * a.imag (); - const double bnorm2 = b.real () * b.real () + b.imag () * b.imag (); - - if (anorm2 > bnorm2) - return 1; - else - return 0; -} - -// select nth largest member from the array values -// Partitioning algorithm, see Numerical recipes chap. 8.5 -template <class ET> -ET selnth (ET *vals, int len, int nth) -{ - ET hinge; - int l, r, mid, i, j; - - l = 0; - r = len - 1; - for (;;) - { - // if partition size is 1 or two, then sort and return - if (r <= l+1) - { - if (r == l+1 && compare<ET> (vals [l], vals [r])) - std::swap (vals [l], vals [r]); - - return vals [nth]; - } - else - { - mid = (l+r) >> 1; - std::swap (vals [mid], vals [l+1]); - - // choose median of l, mid, r to be the hinge element - // and set up sentinels in the borders (order l, l+1 and r) - if (compare<ET> (vals [l], vals [r])) - std::swap (vals [l], vals [r]); - - if (compare<ET> (vals [l+1], vals [r])) - std::swap (vals [l+1], vals [r]); - - if (compare<ET> (vals [l], vals [l+1])) - std::swap (vals [l], vals [l+1]); - - i = l + 1; - j = r; - hinge = vals [l+1]; - for (;;) - { - do i++; while (compare<ET> (hinge, vals [i])); - do j--; while (compare<ET> (vals [j], hinge)); - if (i > j) - break; - std::swap (vals [i], vals [j]); - } - vals [l+1] = vals [j]; - vals [j] = hinge; - if (j >= nth) - r = j - 1; - if (j <= nth) - l = i; - } - } -} - -// Template function for doing the actual filtering -// MT is the type of the matrix to be filtered (Matrix or ComplexMatrix) -// ET is the type of the element of the matrix (double or Complex) -template <class MT, class ET> -octave_value_list do_filtering (MT A, int nth, const boolNDArray dom, MT S) -{ - const int ndims = dom.ndims (); - const octave_idx_type dom_numel = dom.numel (); - const dim_vector dom_size = dom.dims (); - const dim_vector A_size = A.dims (); - - octave_idx_type len = 0; - for (octave_idx_type i = 0; i < dom_numel; i++) - len += dom (i); - if (nth > len - 1) - { - warning("__cordfltn__: nth should be less than number of non-zero values " - "in domain setting nth to largest possible value"); - nth = len - 1; - } - if (nth < 0) - { - warning("__cordfltn__: nth should be non-negative, setting to 1"); - nth = 0; // nth is a c-index - } - - dim_vector dim_offset (dom_size); - for (int i = 0; i < ndims; i++) - dim_offset (i) = (dom_size (i)+1) / 2 - 1; - - // Allocate output - octave_value_list retval; - dim_vector out_size (dom_size); - for (int i = 0; i < ndims; i++) - out_size (i) = A_size (i) - dom_size (i) + 1; - - MT out = MT (out_size); - const octave_idx_type out_numel = out.numel (); - - // Iterate over every element of 'out'. - dim_vector idx_dim (ndims); - Array<octave_idx_type> dom_idx (idx_dim); - Array<octave_idx_type> A_idx (idx_dim); - Array<octave_idx_type> out_idx (idx_dim, 0); - for (octave_idx_type i = 0; i < out_numel; i++) - { - // For each neighbour - OCTAVE_LOCAL_BUFFER (ET, values, len); - int l = 0; - for (int n = 0; n < ndims; n++) - dom_idx (n) = 0; - - for (octave_idx_type j = 0; j < dom_numel; j++) - { - for (int n = 0; n < ndims; n++) - A_idx (n) = out_idx (n) + dom_idx (n); - - if (dom (dom_idx)) - values [l++] = A (A_idx) + S (dom_idx); - - dom.increment_index (dom_idx, dom_size); - } - - // Compute filter result - out (out_idx) = selnth (values, len, nth); - - // Prepare for next iteration - out.increment_index (out_idx, out_size); - - OCTAVE_QUIT; - } - - retval (0) = octave_value (out); - - return retval; -} - -// instantiate template functions -//SH template bool compare<double>(const double, const double); -//SH template double selnth(double *, int, int); -//SH template Complex selnth(Complex *, int, int); -//SH template octave_value_list do_filtering<NDArray, double>(NDArray, int, const boolNDArray, NDArray); -// g++ is broken, explicit instantiation of specialized template function -// confuses the compiler. -//template int compare<Complex>(const Complex, const Complex); -//SH template octave_value_list do_filtering<ComplexNDArray, Complex>(ComplexNDArray, int, const boolNDArray, ComplexNDArray); - -DEFUN_DLD(__cordfltn__, args, , "\ --*- texinfo -*-\n\ -@deftypefn {Loadable Function} __cordfltn__(@var{A}, @var{nth}, @var{domain}, @var{S})\n\ -Implementation of two-dimensional ordered filtering. In general this function\n\ -should NOT be used. Instead use @code{ordfilt2}.\n\ -@seealso{cordflt2, ordfilt2}\n\ -@end deftypefn\n\ -") -{ - octave_value_list retval; - if (args.length () != 4) - { - print_usage (); - return retval; - } - - // nth is an index to an array, thus - 1 - const int nth = (int)args (1).scalar_value () - 1; - const boolNDArray dom = args (2).bool_array_value (); - if (error_state) - { - error ("__cordfltn__: invalid input"); - return retval; - } - - const int ndims = dom.ndims (); - const int args0_ndims = args (0).ndims (); - if (args0_ndims != ndims || args (3).ndims () != ndims) - { - error ("__cordfltn__: input must be of the same dimension"); - return retval; - } - - // Take action depending on input type - if (args (0).is_real_matrix ()) - { - const NDArray A = args (0).array_value (); - const NDArray S = args (3).array_value (); - retval = do_filtering<NDArray, double> (A, nth, dom, S); - } - else if (args (0).is_complex_matrix ()) - { - const ComplexNDArray A = args (0).complex_matrix_value (); - const ComplexNDArray S = args (3).complex_matrix_value (); - retval = do_filtering<ComplexNDArray, Complex> (A, nth, dom, S); - } - else if (args (0).is_int8_type ()) - { - const int8NDArray A = args (0).int8_array_value (); - const int8NDArray S = args (3).int8_array_value (); - retval = do_filtering<int8NDArray, octave_int8> (A, nth, dom, S); - } - else if (args (0).is_int16_type ()) - { - const int16NDArray A = args (0).int16_array_value (); - const int16NDArray S = args (3).int16_array_value (); - retval = do_filtering<int16NDArray, octave_int16> (A, nth, dom, S); - } - else if (args (0).is_int32_type ()) - { - const int32NDArray A = args (0).int32_array_value (); - const int32NDArray S = args (3).int32_array_value (); - retval = do_filtering<int32NDArray, octave_int32> (A, nth, dom, S); - } - else if (args (0).is_int64_type ()) - { - const int64NDArray A = args (0).int64_array_value (); - const int64NDArray S = args (3).int64_array_value (); - retval = do_filtering<int64NDArray, octave_int64> (A, nth, dom, S); - } - else if (args (0).is_uint8_type ()) - { - const uint8NDArray A = args (0).uint8_array_value (); - const uint8NDArray S = args (3).uint8_array_value (); - retval = do_filtering<uint8NDArray, octave_uint8> (A, nth, dom, S); - } - else if (args (0).is_uint16_type ()) - { - const uint16NDArray A = args (0).uint16_array_value (); - const uint16NDArray S = args (3).uint16_array_value (); - retval = do_filtering<uint16NDArray, octave_uint16> (A, nth, dom, S); - } - else if (args (0).is_uint32_type ()) - { - const uint32NDArray A = args (0).uint32_array_value (); - const uint32NDArray S = args (3).uint32_array_value (); - retval = do_filtering<uint32NDArray, octave_uint32> (A, nth, dom, S); - } - else if (args (0).is_uint64_type ()) - { - const uint64NDArray A = args (0).uint64_array_value (); - const uint64NDArray S = args (3).uint64_array_value (); - retval = do_filtering<uint64NDArray, octave_uint64> (A, nth, dom, S); - } - else - { - error ("__cordfltn__: first input should be a real, complex, or integer array"); - } - - return retval; -} Copied: trunk/octave-forge/main/image/src/__spatial_filtering__.cc (from rev 5329, trunk/octave-forge/main/image/src/__cordfltn__.cc) =================================================================== --- trunk/octave-forge/main/image/src/__spatial_filtering__.cc (rev 0) +++ trunk/octave-forge/main/image/src/__spatial_filtering__.cc 2008-10-05 19:18:25 UTC (rev 5334) @@ -0,0 +1,578 @@ +// Copyright (C) 2008 Soren Hauberg +// +// This program 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. +// +// This program 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 this program; if not, see <http://www.gnu.org/licenses/>. + +// The 'compare' and 'selnth' functions are copied from the 'cordflt2' function +// developed by Teemu Ikonen. This work was released under GPLv2 or later. +// -- Soren Hauberg, March 21st, 2008 + +#include <octave/oct.h> + +/** + * Filter functions for ordered filtering. + */ + +template <class ET> +inline bool compare (const ET a, const ET b) +{ + if (a > b) + return 1; + else + return 0; +} + +template <> inline bool compare<Complex> (const Complex a, const Complex b) +{ + const double anorm2 = a.real () * a.real () + a.imag () * a.imag (); + const double bnorm2 = b.real () * b.real () + b.imag () * b.imag (); + + if (anorm2 > bnorm2) + return 1; + else + return 0; +} + +// select nth largest member from the array values +// Partitioning algorithm, see Numerical recipes chap. 8.5 +template <class ET, class MT, class ET_OUT> +ET_OUT selnth (MT &vals, octave_idx_type len, int nth) +{ + ET hinge; + int l, r, mid, i, j; + + l = 0; + r = len - 1; + for (;;) + { + // if partition size is 1 or two, then sort and return + if (r <= l+1) + { + if (r == l+1 && compare<ET> (vals (l), vals (r))) + std::swap (vals (l), vals (r)); + + return vals (nth); + } + else + { + mid = (l+r) >> 1; + std::swap (vals (mid), vals (l+1)); + + // choose median of l, mid, r to be the hinge element + // and set up sentinels in the borders (order l, l+1 and r) + if (compare<ET> (vals (l), vals (r))) + std::swap (vals (l), vals (r)); + + if (compare<ET> (vals (l+1), vals (r))) + std::swap (vals (l+1), vals (r)); + + if (compare<ET> (vals (l), vals (l+1))) + std::swap (vals (l), vals (l+1)); + + i = l + 1; + j = r; + hinge = vals (l+1); + for (;;) + { + do i++; while (compare<ET> (hinge, vals (i))); + do j--; while (compare<ET> (vals (j), hinge)); + if (i > j) + break; + std::swap (vals (i), vals (j)); + } + vals (l+1) = vals (j); + vals (j) = hinge; + if (j >= nth) + r = j - 1; + if (j <= nth) + l = i; + } + } +} + +template <class ET, class MT, class ET_OUT> +ET_OUT min_filt (MT &vals, octave_idx_type len, int not_used) +{ + ET_OUT min_val = vals (0); + for (octave_idx_type i = 1; i < len; i++) + min_val = compare (min_val, vals (i)) ? vals (i) : min_val; + + return min_val; +} + +template <class ET, class MT, class ET_OUT> +ET_OUT max_filt (MT &vals, octave_idx_type len, int not_used) +{ + ET_OUT max_val = vals (0); + for (octave_idx_type i = 1; i < len; i++) + max_val = compare (max_val, vals (i)) ? max_val : vals (i); + + return max_val; +} + +/** + * Filter functions for standard deviation filters + */ + +template <class ET> inline +ET square (const ET a) +{ + return a * a; +} + +template <class ET, class MT, class ET_OUT> +ET_OUT std_filt (MT &vals, octave_idx_type len, int norm) +{ + // Compute mean + ET_OUT mean = 0; + for (octave_idx_type i = 0; i < len; i++) + mean += (ET_OUT)vals (i); + mean /= (ET_OUT)len; + + // Compute sum of square differences from the mean + ET_OUT var = 0; + for (octave_idx_type i = 0; i < len; i++) + var += square ((ET_OUT)vals (i) - mean); + + // Normalise to produce variance + var /= (ET_OUT)norm; + + // Compute std. deviation + return sqrt (var); +} + +/** + * Functions for the entropy filter. + */ + +/* We only need the explicit typed versions */ +template <class ET> +void get_entropy_info (ET &add, int &nbins) +{ +} + +#define ENTROPY_INFO(TYPE, ADD, NBINS) \ + template <> \ + void get_entropy_info<TYPE> (TYPE &add, int &nbins) \ + { \ + add = ADD; \ + if (nbins <= 0) \ + nbins = NBINS; \ + } + +ENTROPY_INFO (bool, 0, 2) +ENTROPY_INFO (octave_int8, 128, 256) +//ENTROPY_INFO (octave_int16, 32768, 65536) +ENTROPY_INFO (octave_uint8, 0, 256) +//ENTROPY_INFO (octave_uint16, 0, 65536) + +#undef ENTROPY_INFO + +template <class ET, class MT, class ET_OUT> +ET_OUT entropy_filt (MT &vals, octave_idx_type len, int nbins) +{ + ET add; + get_entropy_info<ET> (add, nbins); + + // Compute histogram from values + ColumnVector hist (nbins, 0); + for (octave_idx_type i = 0; i < len; i++) + hist (vals (i) + add) ++; + for (octave_idx_type i = 0; i < len; i++) + hist (vals (i) + add) /= (double)len; + + // Compute entropy + double entropy = 0; + for (octave_idx_type i = 0; i < nbins; i++) + { + const double p = hist (i); + if (p > 0) + entropy -= p * log2 (p); + } + + return entropy; +} + +/** + * The function for the range filter + */ +template <class ET, class MT, class ET_OUT> +ET_OUT range_filt (MT &vals, octave_idx_type len, int not_used) +{ + const ET_OUT min_val = min_filt<ET, MT, ET_OUT> (vals, len, not_used); + const ET_OUT max_val = max_filt<ET, MT, ET_OUT> (vals, len, not_used); + + return max_val - min_val; +} + +/** + * The general function for doing the filtering. + */ + +template <class MT, class ET, class MTout, class ETout> +octave_value_list do_filtering (const MT &A, const boolNDArray &dom, + ETout (*filter_function) (MT&, octave_idx_type, int), const MT &S, int arg4) +{ + octave_value_list retval; + + const int ndims = dom.ndims (); + const octave_idx_type dom_numel = dom.numel (); + const dim_vector dom_size = dom.dims (); + const dim_vector A_size = A.dims (); + + octave_idx_type len = 0; + for (octave_idx_type i = 0; i < dom_numel; i++) + len += dom (i); + + dim_vector dim_offset (dom_size); + for (int i = 0; i < ndims; i++) + dim_offset (i) = (dom_size (i)+1) / 2 - 1; + + // Allocate output + dim_vector out_size (dom_size); + for (int i = 0; i < ndims; i++) + out_size (i) = A_size (i) - dom_size (i) + 1; + + MTout out = MTout (out_size); + const octave_idx_type out_numel = out.numel (); + + // Iterate over every element of 'out'. + dim_vector idx_dim (ndims); + Array<octave_idx_type> dom_idx (idx_dim); + Array<octave_idx_type> A_idx (idx_dim); + Array<octave_idx_type> out_idx (idx_dim, 0); + + dim_vector values_size (2); + values_size (0) = 1; + values_size (1) = len; + MT values (values_size); + + for (octave_idx_type i = 0; i < out_numel; i++) + { + // For each neighbour + int l = 0; + for (int n = 0; n < ndims; n++) + dom_idx (n) = 0; + + for (octave_idx_type j = 0; j < dom_numel; j++) + { + for (int n = 0; n < ndims; n++) + A_idx (n) = out_idx (n) + dom_idx (n); + + if (dom (dom_idx)) + values (l++) = A (A_idx) + S (dom_idx); + + dom.increment_index (dom_idx, dom_size); + } + + // Compute filter result + out (out_idx) = filter_function (values, len, arg4); + + // Prepare for next iteration + out.increment_index (out_idx, out_size); + + OCTAVE_QUIT; + } + + retval (0) = octave_value (out); + + return retval; +} + +/** + * The Octave function + */ + +DEFUN_DLD(__spatial_filtering__, args, , "\ +-*- texinfo -*-\n\ +@deftypefn {Loadable Function} __spatial_filtering__(@var{A}, @var{domain},\ +@var{method}, @var{S}, @var{arg})\n\ +Implementation of two-dimensional spatial filtering. In general this function\n\ +should NOT be used -- user interfaces are available in other functions.\n\ +The function computes local characteristics of the image @var{A} in the domain\n\ +@var{domain}. The following values of @var{method} are supported.\n\ +\n\ +@table @asis\n\ +@item \"ordered\"\n\ +Perform ordered filtering. The output in a pixel is the @math{n}th value of a\n\ +sorted list containing the elements of the neighbourhood. The value of @math{n}\n\ +is given in the @var{arg} argument. The corresponding user interface is available\n\ +in @code{ordfilt2} and @code{ordfiltn}.\n\ +@item \"std\"\n\ +Compute the local standard deviation. The correponding user interface is available\n\ +in @code{stdfilt}.\n\ +@item \"entropy\"\n\ +Compute the local entropy. The correponding user interface is available\n\ +in @code{entropyfilt}.\n\ +@item \"range\"\n\ +Compute the local range of the data. The corresponding user interface is\n\ +available in @code{rangefilt}.\n\ +@item \"min\"\n\ +Computes the smallest value in a local neighbourheed.\n\ +@item \"max\"\n\ +Computes the largest value in a local neighbourheed.\n\ +@item \"encoded sign of difference\"\n\ +NOT IMPLEMENTED (local binary patterns style)\n\ +@end table\n\ +@seealso{cordflt2, ordfilt2}\n\ +@end deftypefn\n\ +") +{ + octave_value_list retval; + const int nargin = args.length (); + if (nargin < 4) + { + print_usage (); + return retval; + } + + const boolNDArray dom = args (1).bool_array_value (); + if (error_state) + { + error ("__spatial_filtering__: invalid input"); + return retval; + } + + octave_idx_type len = 0; + for (octave_idx_type i = 0; i < dom.numel (); i++) + len += dom (i); + + const int ndims = dom.ndims (); + const int args0_ndims = args (0).ndims (); + if (args0_ndims != ndims || args (3).ndims () != ndims) + { + error ("__spatial_filtering__: input must be of the same dimension"); + return retval; + } + + + int arg4 = (nargin == 4) ? 0 : args (4).int_value (); + + const std::string method = args (2).string_value (); + if (error_state) + { + error ("__spatial_filtering__: method must be a string"); + return retval; + } + + #define GENERAL_ACTION(MT, FUN, ET, MT_OUT, ET_OUT, FILTER_FUN) \ + { \ + const MT A = args (0).FUN (); \ + const MT S = args (3).FUN (); \ + if (error_state) \ + error ("__spatial_filtering__: invalid input"); \ + else \ + retval = do_filtering<MT, ET, MT_OUT, ET_OUT> (A, dom, FILTER_FUN<ET, MT, ET_OUT>, S, arg4); \ + } + + if (method == "ordered") + { + // Handle input + arg4 -= 1; // convert arg to zero-based index + if (arg4 > len - 1) + { + warning ("__spatial_filtering__: nth should be less than number of non-zero " + "values in domain setting nth to largest possible value"); + arg4 = len - 1; + } + if (arg4 < 0) + { + warning ("__spatial_filtering__: nth should be non-negative, setting to 1"); + arg4 = 0; + } + + // Do the real work + #define ACTION(MT, FUN, ET) \ + GENERAL_ACTION(MT, FUN, ET, MT, ET, selnth) + if (args (0).is_real_matrix ()) + ACTION (NDArray, array_value, double) + else if (args (0).is_complex_matrix ()) + ACTION (ComplexNDArray, complex_array_value, Complex) + else if (args (0).is_bool_matrix ()) + ACTION (boolNDArray, bool_array_value, bool) + else if (args (0).is_int8_type ()) + ACTION (int8NDArray, int8_array_value, octave_int8) + else if (args (0).is_int16_type ()) + ACTION (int16NDArray, int16_array_value, octave_int16) + else if (args (0).is_int32_type ()) + ACTION (int32NDArray, int32_array_value, octave_int32) + else if (args (0).is_int64_type ()) + ACTION (int64NDArray, int64_array_value, octave_int64) + else if (args (0).is_uint8_type ()) + ACTION (uint8NDArray, uint8_array_value, octave_uint8) + else if (args (0).is_uint16_type ()) + ACTION (uint16NDArray, uint16_array_value, octave_uint16) + else if (args (0).is_uint32_type ()) + ACTION (uint32NDArray, uint32_array_value, octave_uint32) + else if (args (0).is_uint64_type ()) + ACTION (uint64NDArray, uint64_array_value, octave_uint64) + else + error ("__spatial_filtering__: first input should be a real, complex, or integer array"); + + #undef ACTION + } + else if (method == "min") + { + // Do the real work + #define ACTION(MT, FUN, ET) \ + GENERAL_ACTION(MT, FUN, ET, MT, ET, min_filt) + if (args (0).is_real_matrix ()) + ACTION (NDArray, array_value, double) + else if (args (0).is_complex_matrix ()) + ACTION (ComplexNDArray, complex_array_value, Complex) + else if (args (0).is_bool_matrix ()) + ACTION (boolNDArray, bool_array_value, bool) + else if (args (0).is_int8_type ()) + ACTION (int8NDArray, int8_array_value, octave_int8) + else if (args (0).is_int16_type ()) + ACTION (int16NDArray, int16_array_value, octave_int16) + else if (args (0).is_int32_type ()) + ACTION (int32NDArray, int32_array_value, octave_int32) + else if (args (0).is_int64_type ()) + ACTION (int64NDArray, int64_array_value, octave_int64) + else if (args (0).is_uint8_type ()) + ACTION (uint8NDArray, uint8_array_value, octave_uint8) + else if (args (0).is_uint16_type ()) + ACTION (uint16NDArray, uint16_array_value, octave_uint16) + else if (args (0).is_uint32_type ()) + ACTION (uint32NDArray, uint32_array_value, octave_uint32) + else if (args (0).is_uint64_type ()) + ACTION (uint64NDArray, uint64_array_value, octave_uint64) + else + error ("__spatial_filtering__: first input should be a real, complex, or integer array"); + + #undef ACTION + } + else if (method == "max") + { + // Do the real work + #define ACTION(MT, FUN, ET) \ + GENERAL_ACTION(MT, FUN, ET, MT, ET, max_filt) + if (args (0).is_real_matrix ()) + ACTION (NDArray, array_value, double) + else if (args (0).is_complex_matrix ()) + ACTION (ComplexNDArray, complex_array_value, Complex) + else if (args (0).is_bool_matrix ()) + ACTION (boolNDArray, bool_array_value, bool) + else if (args (0).is_int8_type ()) + ACTION (int8NDArray, int8_array_value, octave_int8) + else if (args (0).is_int16_type ()) + ACTION (int16NDArray, int16_array_value, octave_int16) + else if (args (0).is_int32_type ()) + ACTION (int32NDArray, int32_array_value, octave_int32) + else if (args (0).is_int64_type ()) + ACTION (int64NDArray, int64_array_value, octave_int64) + else if (args (0).is_uint8_type ()) + ACTION (uint8NDArray, uint8_array_value, octave_uint8) + else if (args (0).is_uint16_type ()) + ACTION (uint16NDArray, uint16_array_value, octave_uint16) + else if (args (0).is_uint32_type ()) + ACTION (uint32NDArray, uint32_array_value, octave_uint32) + else if (args (0).is_uint64_type ()) + ACTION (uint64NDArray, uint64_array_value, octave_uint64) + else + error ("__spatial_filtering__: first input should be a real, complex, or integer array"); + + #undef ACTION + } + else if (method == "range") + { + // Do the real work + #define ACTION(MT, FUN, ET) \ + GENERAL_ACTION(MT, FUN, ET, MT, ET, range_filt) + if (args (0).is_real_matrix ()) + ACTION (NDArray, array_value, double) + else if (args (0).is_complex_matrix ()) + ACTION (ComplexNDArray, complex_array_value, Complex) + else if (args (0).is_bool_matrix ()) + ACTION (boolNDArray, bool_array_value, bool) + else if (args (0).is_int8_type ()) + ACTION (int8NDArray, int8_array_value, octave_int8) + else if (args (0).is_int16_type ()) + ACTION (int16NDArray, int16_array_value, octave_int16) + else if (args (0).is_int32_type ()) + ACTION (int32NDArray, int32_array_value, octave_int32) + else if (args (0).is_int64_type ()) + ACTION (int64NDArray, int64_array_value, octave_int64) + else if (args (0).is_uint8_type ()) + ACTION (uint8NDArray, uint8_array_value, octave_uint8) + else if (args (0).is_uint16_type ()) + ACTION (uint16NDArray, uint16_array_value, octave_uint16) + else if (args (0).is_uint32_type ()) + ACTION (uint32NDArray, uint32_array_value, octave_uint32) + else if (args (0).is_uint64_type ()) + ACTION (uint64NDArray, uint64_array_value, octave_uint64) + else + error ("__spatial_filtering__: first input should be a real, complex, or integer array"); + + #undef ACTION + } + else if (method == "std") + { + // Compute normalisation factor + if (arg4 == 0) + arg4 = len - 1; // unbiased + else + arg4 = len; // max. likelihood + + // Do the real work + #define ACTION(MT, FUN, ET) \ + GENERAL_ACTION(MT, FUN, ET, NDArray, double, std_filt) + if (args (0).is_real_matrix ()) + ACTION (NDArray, array_value, double) + else if (args (0).is_bool_matrix ()) + ACTION (boolNDArray, bool_array_value, bool) + else if (args (0).is_int8_type ()) + ACTION (int8NDArray, int8_array_value, octave_int8) + else if (args (0).is_int16_type ()) + ACTION (int16NDArray, int16_array_value, octave_int16) + else if (args (0).is_int32_type ()) + ACTION (int32NDArray, int32_array_value, octave_int32) + else if (args (0).is_int64_type ()) + ACTION (int64NDArray, int64_array_value, octave_int64) + else if (args (0).is_uint8_type ()) + ACTION (uint8NDArray, uint8_array_value, octave_uint8) + else if (args (0).is_uint16_type ()) + ACTION (uint16NDArray, uint16_array_value, octave_uint16) + else if (args (0).is_uint32_type ()) + ACTION (uint32NDArray, uint32_array_value, octave_uint32) + else if (args (0).is_uint64_type ()) + ACTION (uint64NDArray, uint64_array_value, octave_uint64) + else + error ("__spatial_filtering__: first input should be a real, complex, or integer array"); + + #undef ACTION + } + else if (method == "entropy") + { + // Do the real work + #define ACTION(MT, FUN, ET) \ + GENERAL_ACTION(MT, FUN, ET, NDArray, double, entropy_filt) + if (args (0).is_bool_matrix ()) + ACTION (boolNDArray, bool_array_value, bool) + else if (args (0).is_int8_type ()) + ACTION (int8NDArray, int8_array_value, octave_int8) + else if (args (0).is_uint8_type ()) + ACTION (uint8NDArray, uint8_array_value, octave_uint8) + else + error ("__spatial_filtering__: first input should be a real, complex, or integer array"); + + #undef ACTION + } + else + { + error ("__spatial_filtering__: unknown method '%s'.", method.c_str ()); + } + + return retval; +} Property changes on: trunk/octave-forge/main/image/src/__spatial_filtering__.cc ___________________________________________________________________ Added: svn:mergeinfo + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ha...@us...> - 2009-09-23 11:14:29
|
Revision: 6262 http://octave.svn.sourceforge.net/octave/?rev=6262&view=rev Author: hauberg Date: 2009-09-23 11:14:21 +0000 (Wed, 23 Sep 2009) Log Message: ----------- New function: readexif (from Roderick Kohle) Modified Paths: -------------- trunk/octave-forge/main/image/INDEX Added Paths: ----------- trunk/octave-forge/main/image/inst/readexif.m Modified: trunk/octave-forge/main/image/INDEX =================================================================== --- trunk/octave-forge/main/image/INDEX 2009-09-22 19:16:33 UTC (rev 6261) +++ trunk/octave-forge/main/image/INDEX 2009-09-23 11:14:21 UTC (rev 6262) @@ -10,6 +10,7 @@ imfinfo imginfo bmpwrite jpgread jpgwrite pngread pngwrite + readexif Reshape imcrop imremap Added: trunk/octave-forge/main/image/inst/readexif.m =================================================================== --- trunk/octave-forge/main/image/inst/readexif.m (rev 0) +++ trunk/octave-forge/main/image/inst/readexif.m 2009-09-23 11:14:21 UTC (rev 6262) @@ -0,0 +1,529 @@ +## Copyright (C) 2009 Roderick Koehle koehle(at)users.sourceforge.net +## +## This program 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 2 +## 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 +## <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{exif} =} readexif(@var{filename}, @var{thumbnail}) +## Read EXIF information from JPEG image data. +## +## The exif tag information are returned in the @var{exif} data structure. +## Integer ratios are expressed as column vector. +## For example, a focal number of 2.8 is expressed +## as FNumber=[28; 10]. Otherwise all data are returned by the type +## as specified in the IFD structures. +## +## The filename for the thumbnail image is optional. +## If given, the thumbnail jpeg image will be stored to +## file @var{thumbnail}. +## +## Reference: +## JEITA CP-3451, Exchangeable image file format for digital still cameras: +## Exif Version 2.2 +## +## @seealso{imwrite, imfinfo} +## @end deftypefn + +function exif = readexif(file, thumbnail) + + % Enable the debug flag to see more of the JPG sections. + + debug = false; + + in = fopen(file); + if (in<0) + error('File "%s" not found !', file); + end + + s = fread(in, 1, 'uint16', 'ieee-be'); + + JPEG.SOI = 0xffd8; + JPEG.APP0 = 0xffe0; + JPEG.APP1 = 0xffe1; + JPEG.APP2 = 0xffe2; + JPEG.DQT = 0xffdb; + JPEG.DHT = 0xffc4; + JPEG.DRI = 0xffdd; + JPEG.SOF = 0xffc0; + JPEG.SOS = 0xffda; + JPEG.EOI = 0xffd9; + + % Stop if no Start of Image found + + if s~=JPEG.SOI + error('JPEG Format error - missing start of image tag.'); + end + + exif = []; + + while ~feof(in) + s = fread(in, 1, 'uint16', 'ieee-be'); + + switch s + case JPEG.SOI + case JPEG.APP0 + l = fread(in, 1, 'uint16', 'ieee-be'); + if debug, printf('APP0: %i\n', l); end + fseek(in, l-2, 'cof'); + case JPEG.APP1 + l = fread(in, 1, 'uint16', 'ieee-be'); + if debug, printf('APP1: %i\n', l); end + app1 = fread(in, l-2, 'uchar'); + if nargin==1 + exif = parseexif(app1); + else + exif = parseexif(app1, thumbnail); + end + % stop reading further, remove following break + % if you want to extend this parser. + break; + case JPEG.APP2 + l = fread(in, 1, 'uint16', 'ieee-be'); + if debug, printf('APP2: %i\n', l); end + fseek(in, l-2, 'cof'); + case JPEG.DQT % define quantization table + l = fread(in, 1, 'uint16', 'ieee-be'); + if debug, printf('DQT: %i\n', l); end; + fseek(in, l-2, 'cof'); + case JPEG.DHT % define huffmann table + l = fread(in, 1, 'uint16', 'ieee-be'); + fseek(in, l-2, 'cof'); + if debug, printf('DHT: %i\n', l); end + case JPEG.DRI % define restart interoperability + l = fread(in, 1, 'uint16', 'ieee-be'); + fseek(in, l-2, 'cof'); + if debug, printf('DRI: %i\n', l); end + case JPEG.SOF % start of frame + l = fread(in, 1, 'uint16', 'ieee-be'); + fseek(in, l-2, 'cof'); + if debug, printf('SOF: %i\n', l); end + case JPEG.SOS % start of scan + l = fread(in, 1, 'uint16', 'ieee-be'); + fseek(in, l-2, 'cof'); + if debug, printf('SOS: %i\n', l); end + + % JPEG compressed data comes here ... + break; + + case JPEG.EOI % end of image + printf('EOI'); + otherwise % Skip unknown tags + l = fread(in, 1, 'uint16', 'ieee-be'); + if debug, printf('TAG %04X: %i\n', s, l); end + fseek(in, l-2, 'cof'); + end + end + + fclose(in); +end + +% +% Parse EXIF APP1 section +% +% This routine will parse the APP1 section of an jpeg image. +% If a filename "thumb" is given, the tumbnail image data +% will be exported to given file. +% +% exif = parseexif(data, thumb) +% +function exif = parseexif(data, thumb) + + id = char(data(1:6).'); + if strncmp(id, ['Exif' 0 0], 6) + + % TIFF header + + byteorder = char(data(7:8).'); + littleendian = strncmp(byteorder, 'II', 2); + bigendian = strncmp(byteorder, 'MM', 2); + + tag42 = intn(data(9:10), bigendian); + offset = intn(data(11:14), bigendian); + + if (~littleendian && ~bigendian) || tag42~=42 + error('invalid TIFF header'); + end + + % IFD fields + + exif = ifdparse(tifftags(), data, offset, bigendian); + else + exif = []; + end + + % export thumbnail image + + if nargin==2 && isfield(exif, 'JPEGInterchangeFormat') + i = exif.JPEGInterchangeFormat; + n = exif.JPEGInterchangeFormatLength; + + jpg = data(7+i:7+i+n-1); + out = fopen(thumb, 'w'); + if (out<0), + error('Cannot open file "%s" for writing thumbnail image.', thumb); + end + fwrite(out, jpg, 'uint8'); + fclose(out); + end +end + +function ifd = ifdparse(dict, data, offset, endian) + + debug = false; + + ifd = []; + + while offset + ifd_fields = intn(data(7+offset+(0:1)), endian); + + if debug, printf('Tag Type Count Offset\n'); end + for i=1:ifd_fields + j = 9+offset+(i-1)*12; + ifd_tag = intn(data( j:j+1), endian); + ifd_type = intn(data(j+2:j+3), endian); + ifd_count = intn(data(j+4:j+7), endian); + ifd_offset = intn(data(j+8:j+11), endian); + + name = ifdtagname(dict, ifd_tag); + + if debug, + printf('%04x %04x %08x %08x %s : ', ifd_tag, ifd_type, ... + ifd_count, ifd_offset, name); + end + if ifd_type>0 + n = ifdsize(ifd_type); + + if n*ifd_count<=4 + value = data(j+8:j+8+n*ifd_count-1); + value = reshape(value, n, ifd_count); + else + a = 7+ifd_offset; + b = 7+ifd_offset+n*ifd_count-1; + if (a>0 && b>0 && a<=length(data) && b<=length(data)) + value = data(7+ifd_offset:7+ifd_offset+n*ifd_count-1); + value = reshape(value, n, ifd_count); + else + value = []; + end + end + end + + switch ifd_type + case 01 % unsigned char + ifd.(name) = uint8(value); + if debug, + printf('%02x ', uint8(value)); + printf('\n'); + end + case 02 % Ascii + ifd.(name) = char(value); + if debug, printf('%s\n', char(value)); end + case 03 % 16 bit unsigned int + ifd.(name) = uintn(value, endian); + if debug + printf('%i ', intn(value), endian); + printf('\n'); + end + case 04 % 32 bit unsigned int + ifd.(name) = uintn(value, endian); + if debug, printf('%i\n', uintn(value, endian)); end + case 05 % 32 bit unsigned rational + ifd.(name) = [uintn(value(1:4,:), endian); uintn(value(5:8,:), endian)]; + if debug, printf('%i/%i\n',uintn(value(1:4), endian),uintn(value(5:8)), endian); end + case 07 % unknown + ifd.(name) = uint8(value); + if debug + printf('%02x ', value); + printf('\n'); + end + case 09 % 32 bit signed int + ifd.(name) = intn(value, endian); + if debug, printf('%i\n', intn(value, endian)); end + case 10 % 32 bit signed rational + ifd.(name) = [intn(value(1:4,:), endian); intn(value(5:8,:), endian)]; + if debug, printf('%i/%i\n',intn(value(1:4), endian),intn(value(5:8)), endian); end + otherwise + printf('%02x ', value); + printf('\n'); + end + + switch ifd_tag + case 0x8769, % Exif Pointer + ifd.(name) = ifdparse(exiftags(), data, ifd_offset, endian); + case 0x8825, % GPS Pointer + ifd.(name) = ifdparse(gpstags(), data, ifd_offset, endian); + case 0xa005 % Interoperatibility Pointer + ifd.(name) = ifdparse(dict, data, ifd_offset, endian); +% case 0x927c % Makernotes +% ifd.(name) = ifdparse([], data, ifd_offset, endian); + otherwise + end + end + j = 9+offset+ifd_fields*12; + ifd_next = intn(data(j:j+3), endian); + + offset = ifd_next; + end +end + +% +% Return bytelength for respective IFD type +% +function n = ifdsize(ifd_type) + switch ifd_type + case {1, 2, 7}, n = 1; + case 03 , n = 2; + case {4, 9} , n = 4; + case {5, 10} , n = 8; + otherwise , n = 1; + end +end + + +% +% Convert little endian character vector to integer +% +function y = intn(x, bigendian) + if bigendian + y = polycol(x, int32(256)); + else + y = polycol(flipud(x), int32(256)); + end +end + +function y = uintn(x, bigendian) + if bigendian + y = polycol(x, uint32(256)); + else + y = polycol(flipud(x), uint32(256)); + end +end + +% +% Use own polyval that works with integers, +% it evaluates the number polygon columnwise. +% +% number = polycol(digits, base) +% +function y = polycol(c, x) + y = c(1,:); + for i=2:size(c, 1) + y = y.*x+c(i,:); + end +end + +% +% Query EXIF IFD tagname +% +% Unfortunately, neither MATLAB nor Octave provide a hash functionality, +% so use structures as hash. +% +function name = ifdtagname(dict, key) + k = sprintf('K%04X', key); + if isfield(dict, k) + name = dict.(k); + else + name = sprintf('tag%04X', key); + end +end + +% +% Primary image IFD tags according to Exif 2.2 +% +function dict = tifftags() + t = { + + % TIFF Tags according to EXIF2.2, additional baseline TIFF tags are marked by a '%' + + '0FE' 'NewSubfileType' % + '0FF' 'SubfileType' % + '100' 'ImageWidth' + '101' 'ImageLength' + '102' 'BitsPerSample' + '103' 'Compression' + '106' 'PhotometricInterpretation' + '108' 'CellWidth' % + '109' 'CellLength' % + '10A' 'FillOrder' % + '10E' 'ImageDescription' + '10F' 'Make' + '110' 'Model' + '111' 'StripOffsets' + '112' 'Orientation' + '115' 'SamplesPerPixel' + '116' 'RowsPerStrip' + '117' 'StripByteCounts' + '118' 'MinSampleValue' % + '119' 'MaxSampleValue' % + '11A' 'XResolution' + '11B' 'YResolution' + '11C' 'PlanarConfiguration' + '120' 'FreeOffsets' % + '121' 'FreeByteCounts' % + '122' 'GrayResponseUnit' % + '123' 'GrayResponseCurve' % + '128' 'ResolutionUnit' + '12D' 'TransferFunction' + '131' 'Software' + '132' 'DateTime' + '13B' 'Artist' + '13C' 'HostComputer' % + '13E' 'WhitePoint' + '13F' 'PrimaryChromaticities' + '140' 'ColorMap' % + '152' 'ExtraSamples' % + '201' 'JPEGInterchangeFormat' + '202' 'JPEGInterchangeFormatLength' + '211' 'YCbCrCoefficients' + '212' 'YCbCrSubSampling' + '213' 'YCbCrPositioning' + '214' 'ReferenceBlackWhite' + '8298' 'Copyright' + '8769' 'Exif IFD Pointer' + '8825' 'GPS Info IFD Pointer' + }; + + dict = []; + for i=1:size(t,1) + key = sprintf('K%04X', hex2dec(t{i,1})); + value = t{i,2}; + dict.(key) = strrep(value, ' ', '_'); + end +end + +% +% EXIF private tags +% +function dict = exiftags() + t = { + + % EXIF Tags + + '829A' 'ExposureTime' + '829D' 'FNumber' + '8822' 'ExposureProgram' + '8824' 'SpectralSensitivity' + '8827' 'ISOSpeedRatings' + '8828' 'OECF' + '9000' 'ExifVersion' + '9003' 'DateTimeOriginal' + '9004' 'DateTimeDigitized' + '9101' 'ComponentsConfiguration' + '9102' 'CompressedBitsPerPixel' + '9201' 'ShutterSpeedValue' + '9202' 'ApertureValue' + '9203' 'BrightnessValue' + '9204' 'ExposureBiasValue' + '9205' 'MaxApertureValue' + '9206' 'SubjectDistance' + '9207' 'MeteringMode' + '9208' 'LightSource' + '9209' 'Flash' + '920A' 'FocalLength' + '9214' 'SubjectArea' + '927C' 'MakerNote' + '9286' 'UserComment' + '9290' 'SubsecTime' + '9291' 'SubsecTimeOriginal' + '9292' 'SubsecTimeDigitized' + 'A000' 'FlashpixVersion' + 'A001' 'ColorSpace' + 'A002' 'PixelXDimension' + 'A003' 'PixelYDimension' + 'A004' 'RelatedSoundFile' + 'A005' 'Interoperatibility IFD Pointer' + 'A20B' 'FlashEnergy' + 'A20C' 'SpatialFrequencyResponse' + 'A20E' 'FocalPlaneXResolution' + 'A20F' 'FocalPlaneYResolution' + 'A210' 'FocalPlaneResolutionUnit' + 'A214' 'SubjectLocation' + 'A215' 'ExposureIndex' + 'A217' 'SensingMethod' + 'A300' 'FileSource' + 'A301' 'SceneType' + 'A302' 'CFAPattern' + 'A401' 'CustomRendered' + 'A402' 'ExposureMode' + 'A403' 'WhiteBalance' + 'A404' 'DigitalZoomRatio' + 'A405' 'FocalLengthIn35mmFilm' + 'A406' 'SceneCaptureType' + 'A407' 'GainControl' + 'A408' 'Contrast' + 'A409' 'Saturation' + 'A40A' 'Sharpness' + 'A40B' 'DeviceSettingDescription' + 'A40C' 'SubjectDistanceRange' + 'A420' 'ImageUniqueID' + + % Interoperatibility tags + + '001' 'InteroperatibilityIndex' + '002' 'InteroperatibilityVersion' + '1000' 'RelatedImageFileFormat' + '1001' 'RelatedImageWidth' + '1002' 'RelatedImageLength' + }; + + dict = []; + for i=1:size(t,1) + key = sprintf('K%04X', hex2dec(t{i,1})); + value = t{i,2}; + dict.(key) = strrep(value, ' ', '_'); + end +end + +% +% EXIF GPS tags +% +function dict = gpstags() + t = { + 0 'GPSVersionID' + 1 'GPSLatitudeRef' + 2 'GPSLatitude' + 3 'GPSLongitudeRef' + 4 'GPSLongitude' + 5 'GPSAltitudeRef' + 6 'GPSAltitude' + 7 'GPSTimeStamp' + 8 'GPSSatellites' + 9 'GPSStatus' + 10 'GPSMeasureMode' + 11 'GPSDOP' + 12 'GPSSpeedRef' + 13 'GPSSpeed' + 14 'GPSTrackRef' + 15 'GPSTrack' + 16 'GPSImgDirectionRef' + 17 'GPSImgDirection' + 18 'GPSMapDatum' + 19 'GPSDestLatitudeRef' + 20 'GPSDestLatitude' + 21 'GPSDestLongitudeRef' + 22 'GPSDestLongitude' + 23 'GPSDestBearingRef' + 24 'GPSDestBearing' + 25 'GPSDestDistanceRef' + 26 'GPSDestDistance' + }; + + dict = []; + for i=1:size(t,1) + key = sprintf('K%04X', t{i,1}); + value = t{i,2}; + dict.(key) = strrep(value, ' ', '_'); + end +end + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ha...@us...> - 2009-10-19 20:18:30
|
Revision: 6341 http://octave.svn.sourceforge.net/octave/?rev=6341&view=rev Author: hauberg Date: 2009-10-19 20:18:18 +0000 (Mon, 19 Oct 2009) Log Message: ----------- Mark image I/O functions as deprecated Modified Paths: -------------- trunk/octave-forge/main/image/inst/imginfo.m trunk/octave-forge/main/image/src/jpgread.cc trunk/octave-forge/main/image/src/jpgwrite.cc trunk/octave-forge/main/image/src/pngread.cc trunk/octave-forge/main/image/src/pngwrite.cc Modified: trunk/octave-forge/main/image/inst/imginfo.m =================================================================== --- trunk/octave-forge/main/image/inst/imginfo.m 2009-10-19 18:21:04 UTC (rev 6340) +++ trunk/octave-forge/main/image/inst/imginfo.m 2009-10-19 20:18:18 UTC (rev 6341) @@ -34,6 +34,8 @@ function [h,w] = imginfo (fn) +warning ("'imginfo' has been deprecated in favor of 'imfinfo'. This function will be removed from future versions of the 'image' package"); + [status, res] = system(sprintf("convert -verbose '%s' /dev/null",fn),1); if status, Modified: trunk/octave-forge/main/image/src/jpgread.cc =================================================================== --- trunk/octave-forge/main/image/src/jpgread.cc 2009-10-19 18:21:04 UTC (rev 6340) +++ trunk/octave-forge/main/image/src/jpgread.cc 2009-10-19 20:18:18 UTC (rev 6341) @@ -87,6 +87,7 @@ @seealso{imread, im2double, im2gray, im2rgb}\n\ @end deftypefn\n\ ") { + warning ("'jpgread' has been deprecated in favor of 'imread'. This function will be removed from future versions of the 'image' package."); octave_value_list retval; int nargin = args.length(); Modified: trunk/octave-forge/main/image/src/jpgwrite.cc =================================================================== --- trunk/octave-forge/main/image/src/jpgwrite.cc 2009-10-19 18:21:04 UTC (rev 6340) +++ trunk/octave-forge/main/image/src/jpgwrite.cc 2009-10-19 20:18:18 UTC (rev 6341) @@ -62,6 +62,7 @@ @seealso{jpgread, imwrite}\n\ @end deftypefn\n\ ") { + warning ("'jpgwrite' has been deprecated in favor of 'imwrite'. This function will be removed from future versions of the 'image' package."); octave_value_list retval; int nargin = args.length(); Modified: trunk/octave-forge/main/image/src/pngread.cc =================================================================== --- trunk/octave-forge/main/image/src/pngread.cc 2009-10-19 18:21:04 UTC (rev 6340) +++ trunk/octave-forge/main/image/src/pngread.cc 2009-10-19 20:18:18 UTC (rev 6341) @@ -56,6 +56,7 @@ @end deftypefn\n\ @seealso{imread}") { + warning ("'pngread' has been deprecated in favor of 'imread'. This function will be removed from future versions of the 'image' package."); octave_value_list retval; int nargin = args.length(); Modified: trunk/octave-forge/main/image/src/pngwrite.cc =================================================================== --- trunk/octave-forge/main/image/src/pngwrite.cc 2009-10-19 18:21:04 UTC (rev 6340) +++ trunk/octave-forge/main/image/src/pngwrite.cc 2009-10-19 20:18:18 UTC (rev 6341) @@ -51,6 +51,7 @@ @seealso{imwrite}\n\ @end deftypefn\n\ ") { + warning ("'pngwrite' has been deprecated in favor of 'imwrite'. This function will be removed from future versions of the 'image' package."); octave_value_list retval; int nargin = args.length(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ha...@us...> - 2010-02-08 01:58:05
|
Revision: 6843 http://octave.svn.sourceforge.net/octave/?rev=6843&view=rev Author: hauberg Date: 2010-02-08 01:57:58 +0000 (Mon, 08 Feb 2010) Log Message: ----------- New function: bwconncomp Modified Paths: -------------- trunk/octave-forge/main/image/INDEX Added Paths: ----------- trunk/octave-forge/main/image/inst/bwconncomp.m Modified: trunk/octave-forge/main/image/INDEX =================================================================== --- trunk/octave-forge/main/image/INDEX 2010-02-08 01:25:31 UTC (rev 6842) +++ trunk/octave-forge/main/image/INDEX 2010-02-08 01:57:58 UTC (rev 6843) @@ -60,6 +60,7 @@ Black and white image functions bwarea bwboundaries + bwconncomp bwcount bwdist bweuler Added: trunk/octave-forge/main/image/inst/bwconncomp.m =================================================================== --- trunk/octave-forge/main/image/inst/bwconncomp.m (rev 0) +++ trunk/octave-forge/main/image/inst/bwconncomp.m 2010-02-08 01:57:58 UTC (rev 6843) @@ -0,0 +1,67 @@ +## Copyright (C) 2010 Soren Hauberg +## +## This program 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. +## +## This program 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 this program; If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{cc} = } bwconncomp (@var{BW}) +## @deftypefnx {Function File} {@var{cc} = } bwconncomp (@var{BW}, @var{connectivity}) +## Trace the boundaries of objects in a binary image. +## +## @code{bwconncomp} traces the boundaries of objects in a binary image @var{BW} +## and returns information about them in a structure with the following fields. +## +## @table @t +## @item Connectivity +## The connectivity used in the boundary tracing. +## @item ImageSize +## The size of the image @var{BW}. +## @item NumObjects +## The number of objects in the image @var{BW}. +## @item PixelIdxList +## A cell array containing where each element corresponds to an object in @var{BW}. +## Each element is represented as a vector of linear indices of the boundary of +## the given object. +## @end table +## +## The connectivity used in the tracing is by default 4, but can be changed +## by setting the @var{connectivity} input parameter to 8. Sadly, this is not +## yet implemented. +## @seealso{bwlabel, bwboundaries, ind2sub} +## @end deftypefn + +function CC = bwconncomp (bw, N = 4) + ## Check input + if (nargin < 1) + error ("bwconncomp: not enough input arguments"); + endif + if (!ismatrix (bw) || ndims (bw) != 2) + error ("bwconncomp: first input argument must be a NxM matrix"); + endif + if (!isscalar (N) || !any (N == [4])) #, 8])) + error ("bwconncomp: second input argument must be 4"); + endif + + ## Trace boundaries + B = bwboundaries (bw, N); + + ## Convert from (x, y) index to linear indexing + P = cell (numel (B), 1); + for k = 1:numel (B) + P {k} = sub2ind (size (bw), B {k} (:, 2), B {k} (:, 1)); + endfor + + ## Return result + CC = struct ("Connectivity", N, "ImageSize", size (bw), "NumObjects", numel (B)); + CC.PixelIdxList = P; +endfunction This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ha...@us...> - 2010-02-08 05:25:02
|
Revision: 6844 http://octave.svn.sourceforge.net/octave/?rev=6844&view=rev Author: hauberg Date: 2010-02-08 05:24:56 +0000 (Mon, 08 Feb 2010) Log Message: ----------- New function: regionprops Modified Paths: -------------- trunk/octave-forge/main/image/INDEX Added Paths: ----------- trunk/octave-forge/main/image/inst/regionprops.m Modified: trunk/octave-forge/main/image/INDEX =================================================================== --- trunk/octave-forge/main/image/INDEX 2010-02-08 01:57:58 UTC (rev 6843) +++ trunk/octave-forge/main/image/INDEX 2010-02-08 05:24:56 UTC (rev 6844) @@ -74,6 +74,7 @@ bwborder edge conndef bwhitmiss + regionprops Morhophological Operations imerode imdilate Added: trunk/octave-forge/main/image/inst/regionprops.m =================================================================== --- trunk/octave-forge/main/image/inst/regionprops.m (rev 0) +++ trunk/octave-forge/main/image/inst/regionprops.m 2010-02-08 05:24:56 UTC (rev 6844) @@ -0,0 +1,252 @@ +## Copyright (C) 2010 Soren Hauberg +## +## This program 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. +## +## This program 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 this program; If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{props} = } regionprops (@var{BW}) +## @deftypefnx {Function File} {@var{props} = } regionprops (@var{BW}, @var{properties}, @dots{}) +## Compute object properties in a binary image. +## +## @code{regionprops} computes various properties of the individual objects (as +## identified by @code{bwlabel}) in the binary image @var{BW}. The result is a +## structure array containing an entry per property per object. +## +## The following properties can be computed. +## +## @table @t +## @item "Area" +## The number of pixels in the object. +## @item "EulerNumber" +## @itemx "euler_number" +## The Euler number of the object (see @code{bweuler} for details). +## @item "BoundingBox" +## @itemx "bounding_box" +## The bounding box of the object. This is represented as a 4-vector where the +## first two entries are the @math{x} and @math{y} coordinates of the upper left +## corner of the bounding box, and the two last entries are the width and the +## height of the box. +## @item "Extent" +## The area of the object divided by the area of the bounding box. +## @item "Perimeter" +## The length of the boundary of the object. +## @item "Centroid" +## The center coordinate of the object. +## @item "PixelIdxList" +## @itemx "pixel_idx_list" +## The indices of the pixels in the object. +## @item "FilledArea" +## @itemx "filled_area" +## The area of the object including possible holes. +## @item "PixelList" +## @itemx "pixel_list" +## The actual pixel values inside the object. This is only useful for grey scale +## images. +## @item "FilledImage" +## @itemx "filled_image" +## A binary image with the same size as the object's bounding box that contains +## the object with all holes removed. +## @item "Image" +## An image with the same size as the bounding box that contains the original pixels. +## @item "MaxIntensity" +## @itemx "max_intensity" +## The maximum intensity inside the object. +## @item "MinIntensity" +## @itemx "min_intensity" +## The minimum intensity inside the object. +## @item "WeightedCentroid" +## @itemx "weighted_centroid" +## The centroid of the object where pixel values are used as weights. +## @item "MeanIntensity" +## @itemx "mean_intensity" +## The mean intensity inside the object. +## @item "PixelValues" +## @itemx "pixel_values" +## The pixel values inside the object represented as a vector. +## @end table +## +## The requested properties can either be specified as several input arguments +## or as a cell array of strings. As a short-hand it is also possible to give +## the following strings as arguments. +## +## @table @t +## @item "basic" +## The following properties are computed: @t{"Area"}, @t{"Centroid"} and @t{"BoundingBox"}. +## @item "all" +## All properties are computed. +## @end table +## +## If no properties are given, @t{basic} is assumed. +## @seealso{bwlabel, bwperim, bweuler} +## @end deftypefn + +function retval = regionprops (bw, varargin) + ## Check input + if (nargin < 1) + error ("regionprops: not enough input arguments"); + endif + + if (!ismatrix (bw) || ndims (bw) != 2) + error ("regionprops: first input argument must be a NxM matrix"); + endif + + if (numel (varargin) == 0) + properties = "basic"; + elseif (numel (varargin) == 1 && iscellstr (varargin {1})) + properties = varargin {1}; + elseif (iscellstr (varargin)) + properties = varargin; + else + error ("regionprops: properties must be a cell array of strings"); + endif + + if (ischar (properties) && strcmpi (properties, "basic")) + properties = {"Area", "Centroid", "BoundingBox"}; + elseif (ischar (properties) && strcmpi (properties, "all")) + properties = {"area", "eulernumber", "boundingbox", "extent", "perimeter", ... + "centroid", "pixelidxlist", "filledarea", "pixellist", ... + "filledimage", "image", "maxintensity", "minintensity", ... + "weightedcentroid", "meanintensity", "pixelvalues"}; + elseif (!iscellstr (properties)) + error ("%s %s", "regionprops: properties must be specified as a list of", + "strings or a cell array of strings"); + endif + + ## Get a labelled image + if (!islogical (bw) && all (bw >= 0) && all (bw == round (bw))) + L = bw; # the image was already labelled + num_labels = max (L (:)); + else + [L, num_labels] = bwlabel (logical (bw)); + endif + + ## Compute the properties + retval = struct (); + for k = 1:numel (properties) + switch (lower (properties {k})) + case "area" + for k = 1:num_labels + retval (k).Area = local_area (L == k); + endfor + + case {"eulernumber", "euler_number"} + for k = 1:num_labels + retval (k).EulerNumber = bweuler (L == k); + endfor + + case {"boundingbox", "bounding_box"} + for k = 1:num_labels + retval (k).BoundingBox = local_boundingbox (L == k); + endfor + + case "extent" + for k = 1:num_labels + bb = local_boundingbox (L == k); + area = local_area (L == k); + retval (k).Extent = area / (bb (3) * bb (4)); + endfor + + case "perimeter" + for k = 1:num_labels + retval (k).Perimeter = sum (bwperim (L == k) (:)); + endfor + + case "centroid" + for k = 1:num_labels + [Y, X] = find (L == k); + retval (k).Centroid = [mean(X), mean(Y)]; + endfor + + case {"pixelidxlist", "pixel_idx_list"} + for k = 1:num_labels + retval (k).PixelIdxList = find (L == k); + endfor + + case {"filledarea", "filled_area"} + for k = 1:num_labels + retval (k).FilledArea = sum (bwfill (L == k, "holes") (:)); + endfor + + case {"pixellist", "pixel_list"} + for k = 1:num_labels + [Y, X] = find (L == k); + retval (k).PixelList = [X, Y]; + endfor + + case {"filledimage", "filled_image"} + for k = 1:num_labels + retval (k).FilledImage = bwfill (L == k, "holes"); + endfor + + case "image" + for k = 1:num_labels + tmp = (L == k); + [R, C] = find (tmp); + retval (k).Image = tmp (min (R):max (R), min (C):max (C)); + endfor + + case {"maxintensity", "max_intensity"} + for k = 1:num_labels + retval (k).MaxIntensity = max (bw (L == k) (:)); + endfor + + case {"minintensity", "min_intensity"} + for k = 1:num_labels + retval (k).MaxIntensity = min (bw (L == k) (:)); + endfor + + case {"weightedcentroid", "weighted_centroid"} + for k = 1:num_labels + [Y, X] = find (L == k); + vals = bw (L == k) (:); + vals /= sum (vals); + retval (k).WeightedCentroid = [dot(X, vals), dot(Y, vals)]; + endfor + + case {"meanintensity", "mean_intensity"} + for k = 1:num_labels + retval (k).MaxIntensity = mean (bw (L == k) (:)); + endfor + + case {"pixelvalues", "pixel_values"} + for k = 1:num_labels + retval (k).PixelValues = bw (L == k)(:); + endfor + + #case "orientation" + #case "extrema" + #case "convexarea" + #case "convexhull" + #case "solidity" + #case "conveximage" + #case "subarrayidx" + #case "eccentricity" + #case "majoraxislength" + #case "equivdiameter" + #case "minoraxislength" + + otherwise + error ("regionprops: unsupported property '%s'", properties {k}); + endswitch + endfor +endfunction + +function retval = local_area (bw) + retval = sum (bw (:)); +endfunction + +function retval = local_boundingbox (bw) + [Y, X] = find (bw); + retval = [min(X)-0.5, min(Y)-0.5, max(X)-min(X)+1, max(Y)-min(Y)+1]; +endfunction + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ha...@us...> - 2010-02-08 05:27:12
|
Revision: 6841 http://octave.svn.sourceforge.net/octave/?rev=6841&view=rev Author: hauberg Date: 2010-02-08 00:55:18 +0000 (Mon, 08 Feb 2010) Log Message: ----------- New function: bwboundaries Modified Paths: -------------- trunk/octave-forge/main/image/INDEX trunk/octave-forge/main/image/src/Makefile Added Paths: ----------- trunk/octave-forge/main/image/inst/bwboundaries.m trunk/octave-forge/main/image/src/__imboundary__.cc Modified: trunk/octave-forge/main/image/INDEX =================================================================== --- trunk/octave-forge/main/image/INDEX 2010-02-07 21:39:20 UTC (rev 6840) +++ trunk/octave-forge/main/image/INDEX 2010-02-08 00:55:18 UTC (rev 6841) @@ -59,6 +59,7 @@ nonmax_supress Black and white image functions bwarea + bwboundaries bwcount bwdist bweuler Added: trunk/octave-forge/main/image/inst/bwboundaries.m =================================================================== --- trunk/octave-forge/main/image/inst/bwboundaries.m (rev 0) +++ trunk/octave-forge/main/image/inst/bwboundaries.m 2010-02-08 00:55:18 UTC (rev 6841) @@ -0,0 +1,68 @@ +## Copyright (C) 2010 Soren Hauberg +## +## This program 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. +## +## This program 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 this program; If not, see <http://www.gnu.org/licenses/>. + +function [B, L, num_labels] = bwboundaries (bw, N = 4, options = "holes") + ## Check input + if (nargin < 1) + error ("bwboundaries: not enough input arguments"); + endif + if (!ismatrix (bw) || ndims (bw) != 2) + error ("bwboundaries: first input argument must be a NxM matrix"); + endif + if (!isscalar (N) || !any (N == [4])) #, 8])) + error ("bwboundaries: second input argument must be 4"); + endif + if (!ischar (options) || !any (strcmpi (options, {"holes", "noholes"}))) + error ("bwboundaries: third input must be either \"holes\" or \"noholes\""); + endif + + + ## Warn if the user request more output arguments than our implementation supports + if (nargout > 3) +% warning ("%s %s %s", ... +% "bwboundaries: adjacency matrix output is currently not supported." ... +% "Please contact the Octave-Forge community if you want to contribute" ... +%s "an implementation of this"); + endif + + ## Make sure 'bw' is logical + bw = logical (bw); + + ## Found connected components in 'bw', and treat each of them seperatly + [L, num_labels] = bwlabel (bw, N); + B = cell (num_labels, 1); + for n = 1:num_labels + segment = (L == n); + [R, C] = find (segment); + if (numel (R) > 1) + ## XXX: support 8-neighbors + #B {n} = __imboundary__ (segment, N, R (1), C (1)); + B {n} = __imboundary__ (segment, 4, R (1), C (1)); + else + B {n} = [R, C]; + endif + endfor + + ## If requested, compute internal boundaries as well + if (strcmpi (options, "holes")) + filled = bwfill (bw, "holes", N); + holes = (filled & !bw); + [internal, in_label, lin] = bwboundaries (holes, N, "noholes"); + B (end+1:end+lin, 1) = internal; + + in_label (in_label != 0) += num_labels; + L += in_label; + endif +endfunction Modified: trunk/octave-forge/main/image/src/Makefile =================================================================== --- trunk/octave-forge/main/image/src/Makefile 2010-02-07 21:39:20 UTC (rev 6840) +++ trunk/octave-forge/main/image/src/Makefile 2010-02-08 00:55:18 UTC (rev 6841) @@ -9,7 +9,7 @@ endif all: __spatial_filtering__.oct __bilateral__.oct __custom_gaussian_smoothing__.oct \ - bwlabel.oct bwfill.oct rotate_scale.oct hough_line.oct \ + __imboundary__.oct bwlabel.oct bwfill.oct rotate_scale.oct hough_line.oct \ graycomatrix.oct deriche.oct __bwdist.oct nonmax_supress.oct \ $(JPEG) $(PNG) Added: trunk/octave-forge/main/image/src/__imboundary__.cc =================================================================== --- trunk/octave-forge/main/image/src/__imboundary__.cc (rev 0) +++ trunk/octave-forge/main/image/src/__imboundary__.cc 2010-02-08 00:55:18 UTC (rev 6841) @@ -0,0 +1,162 @@ +// Copyright (C) 2010 Soren Hauberg +// +// This program 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. +// +// This program 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 this program; if not, see <http://www.gnu.org/licenses/>. + +#include <octave/oct.h> + +inline int iseven (const int a) +{ + if ((a % 2) == 0) + return 1; + else + return 0; +} + +Matrix trace_boundary (const boolMatrix &im, const int N, const octave_idx_type r, + const octave_idx_type c) +{ + // Get size information + const octave_idx_type rows = im.rows (); + const octave_idx_type cols = im.columns (); + + // Create list of points + typedef std::pair<int, int> point; + std::list <point> P; + + // Add first point + const point P0 (r, c); // first list element + point P1 (-1, -1); // second list element + point Pn1 (-1, -1); // second last list element + P.push_back (P0); + int len = 1; + + // Create a simple lookup table that translates 'dir' to a row and column offset + const int dir2row4 [] = { 0, -1, 0, +1}; + const int dir2col4 [] = {+1, 0, -1, 0}; + const int dir2row8 [] = { 0, -1, -1, -1, 0, +1, +1, +1}; + const int dir2col8 [] = {+1, +1, 0, -1, -1, -1, 0, +1}; + + // Start searching from there... + int dir = N - 1; + int curr_dir = dir; //(N == 4) ? (dir + 3) % N : (dir + 6 + iseven (dir)) % N; + int delta_r, delta_c; + octave_idx_type row = r, col = c; + while (true) +// for (int z = 0; z < 1000; z++) + { + OCTAVE_QUIT; + + // Get next search direction + if (N == 4) + { + //curr_dir = (dir + 3) % N; + delta_r = dir2row4 [curr_dir]; + delta_c = dir2col4 [curr_dir]; + } + else + { + //curr_dir = (dir + 6 + iseven (dir)) % N; + delta_r = dir2row8 [curr_dir]; + delta_c = dir2col8 [curr_dir]; + } + + // Is a pixel available at the search direction + const octave_idx_type curr_r = row + delta_r; + const octave_idx_type curr_c = col + delta_c; +/* std::cerr << " curr_r = " << curr_r + << " curr_c = " << curr_c + << " curr_dir = " << curr_dir + << " row = " << row + << " colr = " << col + << std::endl; +*/ + if (curr_r >= 0 && curr_r < rows && curr_c >= 0 && curr_c < cols && im (curr_r, curr_c)) + { + // Update 'dir' + dir = curr_dir; + curr_dir = (N == 4) ? (dir + 3) % N : (dir + 6 + iseven (dir)) % N; + + // Add point to list + const point Pn (curr_r, curr_c); + P.push_back (Pn); + len ++; + + // Update 'row' and 'col' + row = curr_r; + col = curr_c; + + // Save the second element of P for the stop criteria + if (len == 2) + { + P1.first = curr_r; + P1.second = curr_c; + } + + // Should we stop? + if (Pn.first == P1.first && Pn.second == P1.second && + Pn1.first == P0.first && Pn1.second == P0.second) + break; + + // Save current point for next time + Pn1 = Pn; + } + else + { + // Update search direction + curr_dir = (curr_dir+1) % N; + } + } // end while + + // Copy data to output matrix + Matrix out (len-1, 2); + std::list<point>::const_iterator iter = P.begin (); + for (int idx = 0; idx < len-2; iter++, idx++) + { + out (idx, 0) = iter->second + 1; + out (idx, 1) = iter->first + 1; + } + out (len-2, 0) = P0.second + 1; + out (len-2, 1) = P0.first + 1; + + return out; +} + +DEFUN_DLD(__imboundary__, args, , "\ +-*- texinfo -*-\n\ +@deftypefn {Function File} __imboundary__ (@var{bw}, @var{N}, @var{r}, @var{c})\n\ +Undocumented internal function.\n\ +User interface is available in @code{bwboundaries}.\n\ +@end deftypefn\n\ +") +{ + // Handle input + octave_value_list retval; + if (args.length () != 4) { + error ("__imboundary__: not enough input arguments"); + return retval; + } + + const boolMatrix im = args (0).bool_matrix_value (); + const int N = (int) args (1).scalar_value (); + const octave_idx_type r = (octave_idx_type) args (2).scalar_value () - 1; + const octave_idx_type c = (octave_idx_type) args (3).scalar_value () - 1; + if (error_state || (N != 4)) // && N != 8)) + error ("__imboundary__: invalid input arguments"); + else + { + Matrix out = trace_boundary (im, N, r, c); + retval.append (out); + } + return retval; +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ha...@us...> - 2010-03-06 09:06:30
|
Revision: 7004 http://octave.svn.sourceforge.net/octave/?rev=7004&view=rev Author: hauberg Date: 2010-03-06 09:06:24 +0000 (Sat, 06 Mar 2010) Log Message: ----------- Remove 'cordfilt2' as it has been deprecated for some time now Modified Paths: -------------- trunk/octave-forge/main/image/INDEX Removed Paths: ------------- trunk/octave-forge/main/image/inst/cordflt2.m Modified: trunk/octave-forge/main/image/INDEX =================================================================== --- trunk/octave-forge/main/image/INDEX 2010-03-06 09:05:33 UTC (rev 7003) +++ trunk/octave-forge/main/image/INDEX 2010-03-06 09:06:24 UTC (rev 7004) @@ -50,7 +50,6 @@ medfilt2 ordfilt2 ordfiltn - cordflt2 uintlut stretchlim makelut applylut Deleted: trunk/octave-forge/main/image/inst/cordflt2.m =================================================================== --- trunk/octave-forge/main/image/inst/cordflt2.m 2010-03-06 09:05:33 UTC (rev 7003) +++ trunk/octave-forge/main/image/inst/cordflt2.m 2010-03-06 09:06:24 UTC (rev 7004) @@ -1,28 +0,0 @@ -## Copyright (C) 2008 Soren Hauberg -## -## This program 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. -## -## This program 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 this program; If not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} cordflt2(@var{A}, @var{nth}, @var{domain}, @var{S}) -## Implementation of two-dimensional ordered filtering. This function has been -## deprecated and should NOT be used. Instead use @code{ordfilt2}. -## @seealso{ordfilt2} -## @end deftypefn - -function retval = cordflt2(A, nth, domain, S) - warning(["cordflt2: this function is deprecated and will be removed in upcoming " - "releases. Use 'ordfilt2' instead."]); - - retval = __spatial_filtering__ (A, domain, "ordered", S, nth); -endfunction This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lx...@us...> - 2010-03-30 07:37:44
|
Revision: 7138 http://octave.svn.sourceforge.net/octave/?rev=7138&view=rev Author: lxop Date: 2010-03-30 07:37:36 +0000 (Tue, 30 Mar 2010) Log Message: ----------- Adding function `iradon\' and a helper function `rho_filter\' Modified Paths: -------------- trunk/octave-forge/main/image/INDEX Added Paths: ----------- trunk/octave-forge/main/image/inst/iradon.m trunk/octave-forge/main/image/inst/rho_filter.m Modified: trunk/octave-forge/main/image/INDEX =================================================================== --- trunk/octave-forge/main/image/INDEX 2010-03-28 08:55:37 UTC (rev 7137) +++ trunk/octave-forge/main/image/INDEX 2010-03-30 07:37:36 UTC (rev 7138) @@ -56,6 +56,8 @@ makelut applylut deriche radon + rho_filter + iradon nonmax_supress Black and white image functions bwarea Added: trunk/octave-forge/main/image/inst/iradon.m =================================================================== --- trunk/octave-forge/main/image/inst/iradon.m (rev 0) +++ trunk/octave-forge/main/image/inst/iradon.m 2010-03-30 07:37:36 UTC (rev 7138) @@ -0,0 +1,169 @@ +## Copyright (C) 2010 Alex Opie <lx...@or...> +## +## +## This program 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. +## +## This program 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 this program; see the file COPYING. If not, see +## <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @defun @var{recon} = iradon (@var{proj}, @var{theta}, @var{interp}, @ +## @var{filter}, @var{scaling}, @var{output_size}) +## +## Performs filtered back-projection on the projections in @var{proj} +## to reconstruct an approximation of the original image. +## +## @var{proj} should be a matrix whose columns are projections of an +## image (or slice). Each element of @var{theta} is used as the angle +## (in degrees) that the corresponding column of @var{proj} was +## projected at. If @var{theta} is omitted, it is assumed that +## projections were taken at evenly spaced angles between 0 and 180 degrees. +## @var{theta} can also be a scalar, in which case it is taken as the +## angle between projections if more than one projection is provided. +## +## @var{interp} determines the type of interpolation that is used +## in the back-projection. It must be one of the types accepted by +## @command{interp1}, and defaults to 'Linear' if it is omitted. +## +## @var{filter} and @var{scaling} determine the type of rho filter +## to apply. See the help for @command{rho_filter} for their use. +## +## @var{output_size} sets the edge length of the output image (it +## is always square). This argument does not scale the image. If it +## is omitted, the length is taken to be +## @group +## 2 * floor (size (proj, 1) / (2 * sqrt (2))). +## @end group +## +## If @var{proj} was obtained using @command{radon}, there is no +## guarantee that the reconstructed image will be exactly the same +## size as the original. +## +## @defunx [@var{recon}, @var{filt}] = iradon (...) +## +## This form also returns the filter frequency response in the vector +## @var{filt}. +## @end defun +## +## Performs filtered back-projection in order to reconstruct an +## image based on its projections. +## +## Filtered back-projection is the most common means of reconstructing +## images from CT scans. It is a two step process: First, each of +## the projections is filtered with a `rho filter', so named due +## to its frequency domain definition, which is simply |rho|, where +## rho is the radial axis in a polar coordinate system. Second, +## the filtered projections are each `smeared' across the image +## space. This is the back-projection part. +## +## Usage example: +## @example +## P = phantom (); +## projections = radon (P, 1:179); +## reconstruction = iradon (filtered_projections, 1:179, 'Spline', 'Hann'); +## figure, imshow (reconstruction, []) +## @end example + +function [recon, filt] = iradon (proj, theta, interp, filter, scaling, output_size) + + if (nargin == 0) + error ("No projections provided to iradon"); + endif + + if (nargin < 6) + output_size = 2 * floor (size (proj, 1) / (2 * sqrt (2))); + endif + if (nargin < 5) || (length (scaling) == 0) + scaling = 1; + endif + if (nargin < 4) || (length (filter) == 0) + filter = "Ram-Lak"; + endif + if (nargin < 3) || (length (interp) == 0) + interp = "linear"; + endif + if (nargin < 2) || (length (theta) == 0) + theta = 180 * (0:1:size (proj, 2) - 1) / size (proj, 2); + endif + + if (isscalar (theta)) && (size (proj, 2) != 1) + theta = (0:size (proj, 2) - 1) * theta; + endif + + if (length (theta) != size (proj, 2)) + error ("iradon: Number of projections does not match number of angles") + endif + if (!isscalar (scaling)) + error ("iradon: Frequency scaling value must be a scalar"); + endif + if (!length (find (strcmpi (interp, {'nearest', 'linear', 'spline', \ + 'pchip', 'cubic'})))) + error ("iradon: Invalid interpolation method specified"); + endif + + ## Convert angles to radians + theta *= pi / 180; + + ## First, filter the projections + [filtered, filt] = rho_filter (proj, filter, scaling); + + ## Next, back-project + recon = back_project (filtered, theta, interp, output_size); + +endfunction + + +function recon = back_project (proj, theta, interpolation, dim) + ## Make an empty image + recon = zeros (dim, dim); + + ## Zero pad the projections if the requested image + ## has a diagonal longer than the projections + diagonal = ceil (dim * sqrt (2)) + 1; + if (size (proj, 1) < diagonal) + diff = 2 * ceil ((diagonal - size (proj, 1)) / 2); + proj = padarray (proj, diff / 2); + endif + + ## Create the x & y values for each pixel + centre = floor ((dim + 1) / 2); + x = (0:dim - 1) - centre + 1; + x = repmat (x, dim, 1); + + y = (dim - 1: -1 : 0)' - centre; + y = repmat (y, 1, dim); + + ## s axis for projections, needed by interp1 + s = (0:size (proj, 1) - 1) - floor (size (proj, 1) / 2); + + ## Sum each projection's contribution + for i = 1:length (theta) + s_dash = (x * cos (theta (i)) + y * sin (theta (i))); + interpolated = interp1 (s, proj (:, i), s_dash (:), ["*", interpolation]); + recon += reshape (interpolated, dim, dim); + endfor + + ## Scale the reconstructed values to their original size + recon *= pi / (2 * length (theta)); + +endfunction + +%!demo +%! P = phantom (); +%! figure, imshow (P, []), title ("Original image") +%! projections = radon (P, 0:179); +%! reconstruction = iradon (projections, 0:179, 'Spline', 'Hann'); +%! figure, imshow (reconstruction, []), title ("Reconstructed image") + +% $Log$ +% 2010-30-03 lxop +% First submitted to Octave-Forge Added: trunk/octave-forge/main/image/inst/rho_filter.m =================================================================== --- trunk/octave-forge/main/image/inst/rho_filter.m (rev 0) +++ trunk/octave-forge/main/image/inst/rho_filter.m 2010-03-30 07:37:36 UTC (rev 7138) @@ -0,0 +1,175 @@ +## Copyright (C) 2010 Alex Opie <lx...@or...> +## +## +## This program 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. +## +## This program 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 this program; see the file COPYING. If not, see +## <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @defun {@var{filtered} =} rho_filter (@var{proj}, @var{type}, @var{scaling}) +## +## Filters the parallel ray projections in the columns of @var{proj}, +## according to the filter type chosen by @var{type}. @var{type} +## can be chosen from +## @itemize +## @item 'none' +## @item 'Ram-Lak' (default) +## @item 'Shepp-Logan' +## @item 'Cosine' +## @item 'Hann' +## @item 'Hamming' +## @end itemize +## +## If given, @var{scaling} determines the proportion of frequencies +## below the nyquist frequency that should be passed by the filter. +## The window function is compressed accordingly, to avoid an abrupt +## truncation of the frequency response. +## +## @defunx {[@var{filtered}, @var{filter}] =} rho_filter (...) +## +## This form also returns the frequency response of the filter in +## the vector @var{filter}. +## +## @end defun +## +## Performs rho filtering on the parallel ray projections provided. +## +## Rho filtering is performed as part of the filtered back-projection +## method of CT image reconstruction. It is the filtered part of +## the name. +## The simplest rho filter is the Ramachadran-Lakshminarayanan (Ram-Lak), +## which is simply |rho|, where rho is the radial component of spatial +## frequency. However, this can cause unwanted amplification of noise, +## which is what the other types attempt to minimise, by introducing +## roll-off into the response. The Hann and Hamming filters multiply +## the standard response by a Hann or Hamming window, respectively. +## The cosine filter is the standard response multiplied by a cosine +## shape, and the Shepp-Logan filter multiplies the response with +## a sinc shape. The 'none' filter performs no filtering, and is +## included for completeness and to enable incorporating this function +## easily into scripts or functions that may offer the ability to choose +## to apply no filtering. +## +## This function is designed to be used by the function @command{iradon}, +## but has been exposed to facilitate custom inverse radon transforms +## and to more clearly break down the process for educational purposes. +## The operations +## @example +## filtered = rho_filter (proj); +## reconstruction = iradon (filtered, 1, 'linear', 'none'); +## @end example +## are exactly equivalent to +## @example +## reconstruction = iradon (proj, 1, 'linear', 'Ram-Lak'); +## @end example +## +## Usage example: +## @example +## P = phantom (); +## projections = radon (P); +## filtered_projections = rho_filter (projections, 'Hamming'); +## reconstruction = iradon (filtered_projections, 1, 'linear', 'none'); +## figure, imshow (reconstruction, []) +## @end example + +function [filtered_proj, filt] = rho_filter (proj, type, scaling) + + filtered_proj = proj; + + if (strcmpi (type, 'none')) + return; + endif + + if (nargin < 2) || (size (type) == 0) + type = 'ram-lak'; + endif + + if (nargin < 3) + scaling = 1; + endif + + if (scaling > 1) + error ('Scaling factor must be in [0,1]'); + endif + + ## Extend the projections to a power of 2 + new_len = 2 * 2^nextpow2 (size (filtered_proj, 1)); + filtered_proj (new_len, 1) = 0; + + ## Scale the frequency response + int_len = (new_len * scaling); + if (mod (floor (int_len), 2)) + int_len = ceil (int_len); + else + int_len = floor (int_len); + endif + + ## Create the basic filter response + rho = scaling * (0:1 / (int_len / 2):1); + rho = [rho'; rho(end - 1:-1:2)']; + + ## Create the window to apply to the filter response + if (strcmpi (type, 'ram-lak')) + filt = 1; + elseif (strcmpi (type, 'hamming')) + filt = fftshift (hamming (length (rho))); + elseif (strcmpi (type, 'hann')) + filt = fftshift (hann (length (rho))); + elseif (strcmpi (type, 'cosine')) + f = 0.5 * (0:length (rho) - 1)' / length (rho); + filt = fftshift (sin (2 * pi * f)); + elseif (strcmpi (type, 'shepp-logan')) + f = (0:length (rho) / 2)' / length (rho); + filt = sin (pi * f) ./ (pi * f); + filt (1) = 1; + filt = [filt; filt(end - 1:-1:2)]; + else + error ('rho_filter: Unknown window type'); + endif + + ## Apply the window + filt = filt .* rho; + + ## Pad the response to the correct length + len_diff = new_len - int_len; + if (len_diff != 0) + pad = len_diff / 2; + filt = padarray (fftshift (filt), pad); + filt = fftshift (filt); + endif + + filtered_proj = fft (filtered_proj); + + ## Perform the filtering + for i = 1:size (filtered_proj, 2) + filtered_proj (:, i) = filtered_proj (:, i) .* filt; + endfor + + ## Finally bring the projections back to the spatial domain + filtered_proj = real (ifft (filtered_proj)); + + ## Chop the projections back to their original size + filtered_proj (size (proj, 1) + 1:end, :) = []; + +endfunction + +%!demo +%! P = phantom (); +%! projections = radon (P); +%! filtered_projections = rho_filter (projections, 'Hamming'); +%! reconstruction = iradon (filtered_projections, 1, 'linear', 'none'); +%! figure, imshow (reconstruction, []) + +% $Log$ +% 2010-03-19 lxop +% Function completed to Matlab compatible level. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ha...@us...> - 2010-12-22 23:02:21
|
Revision: 8034 http://octave.svn.sourceforge.net/octave/?rev=8034&view=rev Author: hauberg Date: 2010-12-22 23:02:14 +0000 (Wed, 22 Dec 2010) Log Message: ----------- New version of bwboundaries (from A Kelly) Modified Paths: -------------- trunk/octave-forge/main/image/INDEX trunk/octave-forge/main/image/inst/bwboundaries.m trunk/octave-forge/main/image/src/Makefile Added Paths: ----------- trunk/octave-forge/main/image/inst/fchcode.m trunk/octave-forge/main/image/src/__boundary__.cc Removed Paths: ------------- trunk/octave-forge/main/image/src/__imboundary__.cc Modified: trunk/octave-forge/main/image/INDEX =================================================================== --- trunk/octave-forge/main/image/INDEX 2010-12-22 08:15:40 UTC (rev 8033) +++ trunk/octave-forge/main/image/INDEX 2010-12-22 23:02:14 UTC (rev 8034) @@ -77,6 +77,7 @@ conndef bwhitmiss regionprops + fchcode Morhophological Operations imerode imdilate Modified: trunk/octave-forge/main/image/inst/bwboundaries.m =================================================================== --- trunk/octave-forge/main/image/inst/bwboundaries.m 2010-12-22 08:15:40 UTC (rev 8033) +++ trunk/octave-forge/main/image/inst/bwboundaries.m 2010-12-22 23:02:14 UTC (rev 8034) @@ -1,4 +1,5 @@ ## Copyright (C) 2010 Soren Hauberg +## Modified December 2010 by Andrew Kelly, IPS Radio & Space Services ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -14,87 +15,81 @@ ## along with this program; If not, see <http://www.gnu.org/licenses/>. ## -*- texinfo -*- -## @deftypefn {Function File} {@var{boundaries} = } bwboundaries (@var{BW}) -## @deftypefnx {Function File} {@var{boundaries} = } bwboundaries (@var{BW}, @ -## @var{connectivity}) -## @deftypefnx {Function File} {@var{boundaries} = } bwboundaries (@var{BW}, @ -## @var{connectivity}, @var{options}) -## @deftypefnx {Function File} {[@var{boundaries}, @var{labels}] = } bwboundaries (@dots{}) -## @deftypefnx {Function File} {[@var{boundaries}, @var{labels}, @var{num_labels}] @ -## = } bwboundaries (@dots{}) +## @deftypefn {Function File} {@var{boundaries} = } bwboundaries(@var{BW}) +## @deftypefnx {Function File} {@var{boundaries} = } bwboundaries(@var{BW}, @var{conn}) +## @deftypefnx {Function File} {@var{boundaries} = } bwboundaries(@var{BW}, @var{conn}, @var{holes}) +## @deftypefnx {Function File} {[@var{boundaries}, @var{labels}] = } bwboundaries(@dots{}) +## @deftypefnx {Function File} {[@var{boundaries}, @var{labels}, @var{num_labels}] = } bwboundaries(@dots{}) ## Trace the boundaries of the objects in a binary image. ## ## @var{boundaries} is a cell array in which each element is the boundary of an -## object in the binary image @var{BW}. The boundary of an object is represented -## by a @var{K} by 2 matrix where each row contains the @var{(x, y)} coordinates -## of a point on the boundary. +## object in the binary image @var{BW}. The clockwise boundary of each object is +## computed by the @code{boundary} function. ## -## By default the boundaries are computed using 4-connectivity. This can be -## changed to 8-connectivity by setting @var{connectivity} to 8. Sadly, this -## feature is not yet implemented. +## By default the boundaries are computed using 8-connectivity. This can be +## changed to 4-connectivity by setting @var{conn} to 4. ## ## By default @code{bwboundaries} computes all boundaries in the image, i.e. ## both interior and exterior object boundaries. This behaviour can be changed -## through the @var{options} input argument. If this is the string @t{"holes"} -## both boundary types are considered. If it is instead @t{"noholes"}, only exterior +## through the @var{holes} input argument. If this is @t{'holes'}, +## both boundary types are considered. If it is instead @t{'noholes'}, only exterior ## boundaries will be traced. ## -## If two or more output arguments are requested, the algorithm also computes -## the labelled image as returned by @code{bwlabel} in @var{labels}. The number +## If two or more output arguments are requested, the algorithm also returns +## the labelled image computed by @code{bwlabel} in @var{labels}. The number ## of labels in this image is optionally returned in @var{num_labels}. -## @seealso{bwlabel} +## @seealso{boundary, bwlabel} ## @end deftypefn -function [B, L, num_labels] = bwboundaries (bw, N = 4, options = "holes") - ## Check input +function [bound, labels, num_labels] = bwboundaries (bw, conn=8, holes="holes") + # check arguments if (nargin < 1) error ("bwboundaries: not enough input arguments"); endif if (!ismatrix (bw) || ndims (bw) != 2) error ("bwboundaries: first input argument must be a NxM matrix"); endif - if (!isscalar (N) || !any (N == [4])) #, 8])) - error ("bwboundaries: second input argument must be 4"); + if (!isscalar (conn) || (conn != 4 && conn != 8)) + error ("bwboundaries: second input argument must be 4 or 8"); endif - if (!ischar (options) || !any (strcmpi (options, {"holes", "noholes"}))) - error ("bwboundaries: third input must be either \"holes\" or \"noholes\""); + if (!ischar (holes) || !any (strcmpi (holes, {'holes', 'noholes'}))) + error ("bwboundaries: third input must be either \'holes\' or \'noholes\'"); endif - - ## Warn if the user request more output arguments than our implementation supports - if (nargout > 3) -% warning ("%s %s %s", ... -% "bwboundaries: adjacency matrix output is currently not supported. " ... -% "Please contact the Octave-Forge community if you want to contribute " ... -% "an implementation of this"); - endif - - ## Make sure 'bw' is logical bw = logical (bw); - ## Found connected components in 'bw', and treat each of them seperatly - [L, num_labels] = bwlabel (bw, N); - B = cell (num_labels, 1); - for n = 1:num_labels - segment = (L == n); - [R, C] = find (segment); - if (numel (R) > 1) - ## XXX: support 8-neighbors -% B {n} = __imboundary__ (segment, 4, R (1), C (1)); - B {n} = __imboundary__ (segment.', N, C (1), R (1)); - else - B {n} = [R, C]; - endif + # process each connected region separately + [labels, num_labels] = bwlabel (bw, conn); + bound = cell (num_labels, 1); + for k = 1:num_labels + bound {k} = __boundary__ ((labels == k), conn); endfor - ## If requested, compute internal boundaries as well - if (strcmpi (options, "holes")) - filled = bwfill (bw, "holes", N); + # compute internal boundaries as well? + if (strcmpi (holes, "holes")) + filled = bwfill (bw, "holes", conn); holes = (filled & !bw); - [internal, in_label, lin] = bwboundaries (holes, N, "noholes"); - B (end+1:end+lin, 1) = internal; - - in_label (in_label != 0) += num_labels; - L += in_label; + [intBounds, intLabels, numIntLabels] = bwboundaries (holes, conn, "noholes"); + + bound (end+1 : end+numIntLabels, 1) = intBounds; + intLabels (intLabels != 0) += num_labels; + labels += intLabels; endif endfunction + +%!demo +%! ## Generate a simple image +%! bw = false (100); +%! bw (10:30, 40:80) = true; +%! bw (40:45, 40:80) = true; +%! +%! ## Find boundaries +%! bounds = bwboundaries (bw); +%! +%! ## Plot result +%! imshow (bw); +%! hold on +%! for k = 1:numel (bounds) +%! plot (bounds {k} (:, 2), bounds {k} (:, 1), 'r', 'linewidth', 2); +%! endfor +%! hold off Added: trunk/octave-forge/main/image/inst/fchcode.m =================================================================== --- trunk/octave-forge/main/image/inst/fchcode.m (rev 0) +++ trunk/octave-forge/main/image/inst/fchcode.m 2010-12-22 23:02:14 UTC (rev 8034) @@ -0,0 +1,88 @@ +## Copyright (C) 2010 Andrew Kelly, IPS Radio & Space Services +## +## This program 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. +## +## This program 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 this program; If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{fcc} = } fchcode (@var{bound}) +## Determine the Freeman chain code for a boundary. +## +## @code{fchcode} computes the Freeman chain code for the @var{n}-connected +## boundary @var{bound}. @var{n} must be either 8 or 4. +## +## @var{bound} is a K-by-2 matrix containing the row/column coordinates of points +## on the boundary. Optionally, the first point can be repeated as the last point, +## resulting in a (K+1)-by-2 matrix. +## +## @var{fcc} is a structure containing the following elements. +## +## @example +## x0y0 = Row/column coordinates where the code starts (1-by-2) +## fcc = Freeman chain code (1-by-K) +## diff = First difference of fcc (1-by-K) +## @end example +## +## The code uses the following directions. +## +## @example +## 3 2 1 +## 4 . 0 +## 5 6 7 +## @end example +## +## @seealso{bwboundaries} +## @end deftypefn + +function fcc = fchcode (bound) + + # ensure the boundary start and end points are the same + if (!isempty (bound) && !isequal (bound (1, :), bound (end, :))) + bound = [bound; bound(1, :)]; + endif + + # number of boundary points + n = max (0, rows (bound)-1); + + # structure in which to return results + fcc = struct (\ + 'x0y0', zeros (1, n), \ + 'fcc', zeros (1, n), \ + 'diff', zeros (1, n) \ + ); + + # an empty boundary? + if (isempty (bound)) + return; + endif + + # direction map + dir = [3, 2, 1; \ + 4, NaN, 0; \ + 5, 6, 7]; + + # coordinates + ROW = 1; + COL = 2; + + # direction changes as row/column indexes into DIR + ch = 2 + diff (bound, 1, ROW); + + # starting point + fcc.x0y0 = bound (1, :); + + # chain code + fcc.fcc = dir (sub2ind (size (dir), ch (:, ROW), ch (:, COL)))'; + + # chain code difference + fcc.diff = mod (diff ([fcc.fcc, fcc.fcc(1)]), 8); +endfunction Modified: trunk/octave-forge/main/image/src/Makefile =================================================================== --- trunk/octave-forge/main/image/src/Makefile 2010-12-22 08:15:40 UTC (rev 8033) +++ trunk/octave-forge/main/image/src/Makefile 2010-12-22 23:02:14 UTC (rev 8034) @@ -1,5 +1,5 @@ all: __spatial_filtering__.oct __bilateral__.oct __custom_gaussian_smoothing__.oct \ - __imboundary__.oct bwlabel.oct bwfill.oct rotate_scale.oct hough_line.oct \ + __boundary__.oct bwlabel.oct bwfill.oct rotate_scale.oct hough_line.oct \ graycomatrix.oct deriche.oct __bwdist.oct nonmax_supress.oct %.oct: %.cc Added: trunk/octave-forge/main/image/src/__boundary__.cc =================================================================== --- trunk/octave-forge/main/image/src/__boundary__.cc (rev 0) +++ trunk/octave-forge/main/image/src/__boundary__.cc 2010-12-22 23:02:14 UTC (rev 8034) @@ -0,0 +1,181 @@ +/* +Copyright (C) 2010 Andrew Kelly, IPS Radio & Space Services + +This program 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. + +This program 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 this program; If not, see <http://www.gnu.org/licenses/>. +*/ + +/** + * Oct-file to trace the boundary of an object in a binary image. + * + * b = boundary(region, conn=8) + */ +#include <octave/oct.h> + +using namespace std; + +DEFUN_DLD(__boundary__, args, nargout, +"-*- texinfo -*-\n\ +@deftypefn {Function File} {@var{b} = } boundary(@var{region})\n\ +@deftypefnx {Function File} {@var{b} = } boundary(@var{region}, @var{conn})\n\ +Trace the boundary of an object in a binary image.\n\ +\n\ +@code{boundary} computes the exterior clockwise boundary of the single \ +@var{conn}-connected object represented by the non-zero pixels \ +of @var{region}. It uses an algorithm based on Moore-neighbour tracing.\n\ +\n\ +@var{conn} can be either 8 (the default) or 4.\n\ +\n\ +@var{b} is an N-by-2 matrix containing the row/column coordinates of points \ +on the boundary. The first boundary point is the first non-zero \ +pixel of @var{region}, as determined by @code{find}. The last boundary \ +point is the same as the first.\n\ +@seealso{boundaries, bwlabel, find}\n\ +@end deftypefn") +{ + octave_value_list retval; + + enum { ROW, COL }; + + // check number of arguments + const int nargin = args.length (); + if (nargin > 2 || nargout != 1) + { + error ("__boundary__: wrong number of input arguments"); + return retval; + } + + // extract arguments + const boolMatrix unpadded = args (0).bool_matrix_value (); + const int conn = (nargin > 1) + ? (int) args (1).scalar_value () + : 8; + + if (error_state) + { + error ("__boundary__: internal error"); + return retval; + } + + // pad to avoid boundary issues + int rows = unpadded.rows (); + int cols = unpadded.columns (); + boolMatrix region (rows + 2, cols + 2, false); + for (int r = 0; r < rows; r++) + for (int c = 0; c < cols; c++) + region.elem (r+1, c+1) = unpadded (r, c); + + // the padded size + rows += 2; + cols += 2; + + // find the (first two) true pixels, if any + std::vector <int> pixels; + for (int i = 0; pixels.size () < 2 && i < region.numel (); ++i) + if (region.elem (i)) + pixels.push_back (i); + + if (pixels.empty ()) + return retval; + + // the starting boundary point + const int start = pixels [0]; + std::vector <int> bound; + bound.push_back (start); + + // is this the only point? + if (pixels.size () == 1) + bound.push_back (start); + + // otherwise, find the boundary by tracing the Moore neighbourhood of its pixels + // + // 8-connected: 7 0 1 4-connected: 0 + // 6 . 2 3 . 1 + // 5 4 3 2 + else + { + // relative row/column positions + static const int row8 [] = {-1, -1, 0, 1, 1, 1, 0, -1}; + static const int col8 [] = { 0, 1, 1, 1, 0, -1, -1, -1}; + static const int row4 [] = {-1, 0, 1, 0 }; + static const int col4 [] = { 0, 1, 0, -1 }; + const int* mr = (conn == 4) ? row4 : row8; + const int* mc = (conn == 4) ? col4 : col8; + + // next after backing-up + static const int back8 [] = {7, 7, 1, 1, 3, 3, 5, 5}; + static const int back4 [] = {3, 0, 1, 2}; + const int* mBack = (conn == 4) ? back4 : back8; + + // relative indexes into the region for the Moore neighbourhood pixels + int mi [conn]; + for (int i = 0; i < conn; ++i) + mi[i] = mr[i] + (rows * mc [i]); + + // next neighbourhood pixel + static const int next8 [] = {1, 2, 3, 4, 5, 6, 7, 0}; + static const int next4 [] = {1, 2, 3, 0}; + const int* mNext = (conn == 4) ? next4 : next8; + + // the final boundary point to be visited + int finish = 0; + for (int i = 0; i < conn; ++i) + if (region.elem(start + mi [i])) + finish = start + mi [i]; + + // look for the next boundary point, starting at the next neighbour + int bp = start; + int mCurrent = mNext [0]; + bool done = false; + while (!done) + { + // next neighbour + int cp = bp + mi [mCurrent]; + + // if this pixel is false, try the next one + if (!region.elem (cp)) + { + mCurrent = mNext [mCurrent]; + } + // otherwise, we have another boundary point + else + { + bound.push_back (cp); + + // either we're back at the start for the last time + if (bp == finish && cp == start) + { + done = true; + } + // or we step back to where we came in from, and continue + else + { + bp = cp; + mCurrent = mBack [mCurrent]; + } + } + } + } + + // convert boundary points to row/column coordinates + Matrix b (bound.size (), 2); + for (unsigned int i = 0; i < bound.size (); i++) + { + const int point = bound [i]; + b (i, ROW) = point % rows; + b (i, COL) = point / rows; + } + + retval.append (b); + return retval; +} Deleted: trunk/octave-forge/main/image/src/__imboundary__.cc =================================================================== --- trunk/octave-forge/main/image/src/__imboundary__.cc 2010-12-22 08:15:40 UTC (rev 8033) +++ trunk/octave-forge/main/image/src/__imboundary__.cc 2010-12-22 23:02:14 UTC (rev 8034) @@ -1,162 +0,0 @@ -// Copyright (C) 2010 Soren Hauberg -// -// This program 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. -// -// This program 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 this program; if not, see <http://www.gnu.org/licenses/>. - -#include <octave/oct.h> - -inline int iseven (const int a) -{ - if ((a % 2) == 0) - return 1; - else - return 0; -} - -Matrix trace_boundary (const boolMatrix &im, const int N, const octave_idx_type r, - const octave_idx_type c) -{ - // Get size information - const octave_idx_type rows = im.rows (); - const octave_idx_type cols = im.columns (); - - // Create list of points - typedef std::pair<int, int> point; - std::list <point> P; - - // Add first point - const point P0 (r, c); // first list element - point P1 (-1, -1); // second list element - point Pn1 (-1, -1); // second last list element - P.push_back (P0); - int len = 1; - - // Create a simple lookup table that translates 'dir' to a row and column offset - const int dir2row4 [] = { 0, -1, 0, +1}; - const int dir2col4 [] = {+1, 0, -1, 0}; - const int dir2row8 [] = { 0, -1, -1, -1, 0, +1, +1, +1}; - const int dir2col8 [] = {+1, +1, 0, -1, -1, -1, 0, +1}; - - // Start searching from there... - int dir = N - 1; - int curr_dir = dir; //(N == 4) ? (dir + 3) % N : (dir + 6 + iseven (dir)) % N; - int delta_r, delta_c; - octave_idx_type row = r, col = c; - while (true) -// for (int z = 0; z < 1000; z++) - { - OCTAVE_QUIT; - - // Get next search direction - if (N == 4) - { - //curr_dir = (dir + 3) % N; - delta_r = dir2row4 [curr_dir]; - delta_c = dir2col4 [curr_dir]; - } - else - { - //curr_dir = (dir + 6 + iseven (dir)) % N; - delta_r = dir2row8 [curr_dir]; - delta_c = dir2col8 [curr_dir]; - } - - // Is a pixel available at the search direction - const octave_idx_type curr_r = row + delta_r; - const octave_idx_type curr_c = col + delta_c; -/* std::cerr << " curr_r = " << curr_r - << " curr_c = " << curr_c - << " curr_dir = " << curr_dir - << " row = " << row - << " colr = " << col - << std::endl; -*/ - if (curr_r >= 0 && curr_r < rows && curr_c >= 0 && curr_c < cols && im (curr_r, curr_c)) - { - // Update 'dir' - dir = curr_dir; - curr_dir = (N == 4) ? (dir + 3) % N : (dir + 6 + iseven (dir)) % N; - - // Add point to list - const point Pn (curr_r, curr_c); - P.push_back (Pn); - len ++; - - // Update 'row' and 'col' - row = curr_r; - col = curr_c; - - // Save the second element of P for the stop criteria - if (len == 2) - { - P1.first = curr_r; - P1.second = curr_c; - } - - // Should we stop? - if (Pn.first == P1.first && Pn.second == P1.second && - Pn1.first == P0.first && Pn1.second == P0.second) - break; - - // Save current point for next time - Pn1 = Pn; - } - else - { - // Update search direction - curr_dir = (curr_dir+1) % N; - } - } // end while - - // Copy data to output matrix - Matrix out (len-1, 2); - std::list<point>::const_iterator iter = P.begin (); - for (int idx = 0; idx < len-2; iter++, idx++) - { - out (idx, 0) = iter->second + 1; - out (idx, 1) = iter->first + 1; - } - out (len-2, 0) = P0.second + 1; - out (len-2, 1) = P0.first + 1; - - return out; -} - -DEFUN_DLD(__imboundary__, args, , "\ --*- texinfo -*-\n\ -@deftypefn {Function File} __imboundary__ (@var{bw}, @var{N}, @var{r}, @var{c})\n\ -Undocumented internal function.\n\ -User interface is available in @code{bwboundaries}.\n\ -@end deftypefn\n\ -") -{ - // Handle input - octave_value_list retval; - if (args.length () != 4) { - error ("__imboundary__: not enough input arguments"); - return retval; - } - - const boolMatrix im = args (0).bool_matrix_value (); - const int N = (int) args (1).scalar_value (); - const octave_idx_type r = (octave_idx_type) args (2).scalar_value () - 1; - const octave_idx_type c = (octave_idx_type) args (3).scalar_value () - 1; - if (error_state || (N != 4)) // && N != 8)) - error ("__imboundary__: invalid input arguments"); - else - { - Matrix out = trace_boundary (im, N, r, c); - retval.append (out); - } - return retval; -} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2011-04-13 21:19:47
|
Revision: 8203 http://octave.svn.sourceforge.net/octave/?rev=8203&view=rev Author: thomas-weber Date: 2011-04-13 21:19:36 +0000 (Wed, 13 Apr 2011) Log Message: ----------- Fix failing tests due to Octave checking for the matrix type in assert() Modified Paths: -------------- trunk/octave-forge/main/image/inst/imtophat.m trunk/octave-forge/main/image/src/bwlabel.cc Modified: trunk/octave-forge/main/image/inst/imtophat.m =================================================================== --- trunk/octave-forge/main/image/inst/imtophat.m 2011-04-12 17:34:11 UTC (rev 8202) +++ trunk/octave-forge/main/image/inst/imtophat.m 2011-04-13 21:19:36 UTC (rev 8203) @@ -56,7 +56,7 @@ %!test %! I = [1 1 1; 1 1 1; 1 1 1;]; %! se = [1 1; 0 1;]; -%! result = imtophat(I, se); +%! result = logical(imtophat(I, se)); %! expected = 0.5 < [0 0 1; 0 0 1; 1 1 1]; %! assert(expected, result); Modified: trunk/octave-forge/main/image/src/bwlabel.cc =================================================================== --- trunk/octave-forge/main/image/src/bwlabel.cc 2011-04-12 17:34:11 UTC (rev 8202) +++ trunk/octave-forge/main/image/src/bwlabel.cc 2011-04-13 21:19:36 UTC (rev 8203) @@ -298,7 +298,7 @@ } /* -%!assert(bwlabel([0 1 0; 0 0 0; 1 0 1]),[0 1 0; 0 0 0; 2 0 3]); +%!assert(bwlabel(logical([0 1 0; 0 0 0; 1 0 1])),[0 1 0; 0 0 0; 2 0 3]); */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <car...@us...> - 2011-10-31 02:31:42
|
Revision: 8890 http://octave.svn.sourceforge.net/octave/?rev=8890&view=rev Author: carandraug Date: 2011-10-31 02:31:35 +0000 (Mon, 31 Oct 2011) Log Message: ----------- dilate: bug fixes on octave core (somewhere in filter2) make dilate work correctly with non-symmetric SE. Updating version of dependency Modified Paths: -------------- trunk/octave-forge/main/image/DESCRIPTION trunk/octave-forge/main/image/inst/dilate.m Modified: trunk/octave-forge/main/image/DESCRIPTION =================================================================== --- trunk/octave-forge/main/image/DESCRIPTION 2011-10-27 21:44:50 UTC (rev 8889) +++ trunk/octave-forge/main/image/DESCRIPTION 2011-10-31 02:31:35 UTC (rev 8890) @@ -9,7 +9,7 @@ The package also provides functions for feature extraction, image statistics, spatial and geometric transformations, morphological operations, linear filtering, and much more. -Depends: octave (>= 3.2.0) +Depends: octave (>= 3.4.0) Autoload: yes License: GPL version 2 or later Url: http://octave.sf.net Modified: trunk/octave-forge/main/image/inst/dilate.m =================================================================== --- trunk/octave-forge/main/image/inst/dilate.m 2011-10-27 21:44:50 UTC (rev 8889) +++ trunk/octave-forge/main/image/inst/dilate.m 2011-10-31 02:31:35 UTC (rev 8890) @@ -68,7 +68,6 @@ ## Filtering must be done with the reflection of the structuring element (they ## are not always symmetrical) SE = imrotate(SE, 180); - for i=1:n # create result matrix BW1=filter2(SE,BW1)>0; @@ -81,10 +80,7 @@ %! dilate(eye(5),ones(2,2)) %! % returns a thick diagonal. - - +## tests %!assert(dilate(eye(3),[1])==eye(3)); # using [1] as a mask returns the same value %!assert(dilate(eye(3),[1,0,0])==[0,0,0;1,0,0;0,1,0]); # check if it works with non-symmetric SE -## TODO the next assertion is commented since we do not know how the right answer for the calculation -%!##assert(dilate(eye(3),[1,0,0,0])==XXX); # test if center is correctly calculated on even masks - +%!assert(dilate(eye(3),[1,0,0,0])==[0,0,0;1,0,0;0,1,0]); # test if center is correctly calculated on even masks This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <car...@us...> - 2011-11-01 14:21:26
|
Revision: 8909 http://octave.svn.sourceforge.net/octave/?rev=8909&view=rev Author: carandraug Date: 2011-11-01 14:21:15 +0000 (Tue, 01 Nov 2011) Log Message: ----------- image: new utility functions iptcheckstrs, iptnum2ordinal, iptcheckmap and iptchecknargin Modified Paths: -------------- trunk/octave-forge/main/image/INDEX Added Paths: ----------- trunk/octave-forge/main/image/inst/iptcheckmap.m trunk/octave-forge/main/image/inst/iptchecknargin.m trunk/octave-forge/main/image/inst/iptcheckstrs.m trunk/octave-forge/main/image/inst/iptnum2ordinal.m Modified: trunk/octave-forge/main/image/INDEX =================================================================== --- trunk/octave-forge/main/image/INDEX 2011-11-01 14:11:37 UTC (rev 8908) +++ trunk/octave-forge/main/image/INDEX 2011-11-01 14:21:15 UTC (rev 8909) @@ -109,3 +109,8 @@ rangefilt stdfilt entropyfilt +Utilities + iptnum2ordinal + iptcheckstrs + iptchecknargin + iptcheckmap Added: trunk/octave-forge/main/image/inst/iptcheckmap.m =================================================================== --- trunk/octave-forge/main/image/inst/iptcheckmap.m (rev 0) +++ trunk/octave-forge/main/image/inst/iptcheckmap.m 2011-11-01 14:21:15 UTC (rev 8909) @@ -0,0 +1,49 @@ +## Copyright (C) 2011 Carnë Draug <car...@gm...> +## +## This program 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. +## +## This program 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 this program; if not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {} iptcheckmap (@var{in}, @var{func_name}, @var{var_name}, @var{pos}) +## Check if argument is valid colormap. +## +## If @var{in} is not a valid colormap, gives a properly formatted error message. +## @var{func_name} is the name of the function to be used on the error message, +## @var{var_name} the name of the argument being checked (for the error message), +## and @var{pos} the position of the argument in the input. +## +## A valid colormap is a 2-D matrix with 3 columns of doubles with values between +## 0 and 1 (inclusive), that refer to the intensity levels of red, green and blue. +## +## @seealso{colormap} +## @end deftypefn + +function iptcheckmap (in, func_name, var_name, pos) + + if (nargin != 4) + print_usage; + elseif (!ischar (func_name)) + error ("Argument func_name must be a string"); + elseif (!ischar (var_name)) + error ("Argument var_name must be a string"); + elseif (!isnumeric (pos) || !isscalar (pos) || !isreal (pos) || pos <= 0 || rem (pos, 1) != 0) + error ("Argument pos must be a real positive integer"); + endif + + if (!strcmp (class(in), "double") || columns (in) != 3 || ndims (in) != 2 || !isreal (in) || min (in(:) < 0 || max (in(:) > 1) + error ("Function %s expected input number %d, %s, to be a valid colormap.\n ... + Valid colormaps must be nonempty, double, 2-D matrices with 3 columns.", ... + func_name, pos, var_name); + endif + +endfunction Added: trunk/octave-forge/main/image/inst/iptchecknargin.m =================================================================== --- trunk/octave-forge/main/image/inst/iptchecknargin.m (rev 0) +++ trunk/octave-forge/main/image/inst/iptchecknargin.m 2011-11-01 14:21:15 UTC (rev 8909) @@ -0,0 +1,56 @@ +## Copyright (C) 2011 Carnë Draug <car...@gm...> +## +## This program 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. +## +## This program 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 this program; if not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {} iptchecknargin (@var{low}, @var{high}, @var{in}, @var{func_name}) +## Checks for correct number of arguments. +## +## This function returns an error unless @var{in} is between the values of +## @var{low} and @var{high}. It does nothing otherwise. They all must be non +## negative scalar integers. @var{high} can also be Inf. +## +## @var{func_name} is the name of the function to be used on the error message. +## +## @seealso{error, nargin, nargout, narginchk, nargoutchk} +## @end deftypefn + +function iptchecknargin (low, high, in, func_name) + + if (nargin != 4) + print_usage; + elseif (!isnumeric (low) || !isscalar (low) || !isreal (low) || low < 0 || !isfinite (low) || rem (low, 1) != 0) + error ("Argument 'low' must be a non-negative scalar integer"); + elseif (!isnumeric (high) || !isscalar (high) || !isreal (high) || low < 0 || (isfinite (high) && rem (low, 1) != 0)) + error ("Argument 'high' must be a non-negative scalar integer or Inf"); + elseif (!isnumeric (in) || !isscalar (in) || !isreal (in) || in < 0 || !isfinite (in) || rem (in, 1) != 0) + error ("Argument 'in' must be a non-negative scalar integer"); + elseif (!ischar (func_name)) + error ("Argument 'func_name' must be a string"); + elseif (low > high) + error ("Minimun number of arguments cannot be larger than maximum number of arguments") + endif + + if (in < low) + error ("Not enough input arguments."); + elseif (in > high) + error ("Too many input arguments."); + endif + +endfunction + +%!test ('iptchecknargin (0, 2, 1, "func")'); # check simple works +%!test ('iptchecknargin (0, Inf, 1, "func")'); # check Inf on max +%!fail ('iptchecknargin (3, 2, 1, "func")'); # check fail min >max +%!fail ('iptchecknargin (2, 3, 1, "func")'); # check fail in out of range Added: trunk/octave-forge/main/image/inst/iptcheckstrs.m =================================================================== --- trunk/octave-forge/main/image/inst/iptcheckstrs.m (rev 0) +++ trunk/octave-forge/main/image/inst/iptcheckstrs.m 2011-11-01 14:21:15 UTC (rev 8909) @@ -0,0 +1,64 @@ +## Copyright (C) 2011 Carnë Draug <car...@gm...> +## +## This program 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. +## +## This program 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 this program; if not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{valid} =} iptcheckstrs (@var{in}, @var{valid_str}, @var{func_name}, @var{var_name}, @var{pos}) +## Check if argument is a valid string. +## +## If @var{in} is not a string, present in the cell array of strings +## @var{valid_str} gives a properly formatted error message. Otherwise, +## @var{valid} is the matched string. The performed matching is case-insensitive. +## +## @var{func_name} is the name of the function to be used on the error message, +## @var{var_name} the name of the argument being checked (for the error message), +## and @var{pos} the position of the argument in the input. +## +## @seealso{strcmp, strcmpi, find} +## @end deftypefn + +function out = iptcheckstrs (in, valid_str, func_name, var_name, pos) + + if (nargin != 5) + print_usage; + elseif (!ischar (in)) + error ("Argument 'in' must be a string."); + elseif (!iscellstr (valid_str)) + error ("Argument 'valid_str' must be a cell array of strings."); + elseif (!ischar (func_name)) + error ("Argument 'func_name' must be a string"); + elseif (!ischar (var_name)) + error ("Argument 'var_name' must be a string"); + elseif (!isnumeric (pos) || !isscalar (pos) || !isreal (pos) || pos <= 0 || rem (pos, 1) != 0) + error ("Argument 'pos' must be a real positive integer"); + endif + + idx = find (strcmpi (valid_str, in) == 1, 1, "first"); + + if (isempty (idx)) + valid_str = cellfun (@(x) cstrcat (x, ", "), valid_str, "UniformOutput", false); + valid_str = cstrcat (valid_str{:}); + error("Function %s expected its %s input argument, %s, to match one of these strings:\n... + %s\n... + The input, '%s', did not match any of the valid strings.", ... + func_name, iptnum2ordinal (pos), var_name, valid_str(1:end-2), in); + else + out = valid_str{idx}; + endif + +endfunction + +%!assert (iptcheckstrs ("two", {"one", "two", "three"}, "func", "var", 1) == "two" ); # check simple works +%!assert (iptcheckstrs ("Two", {"one", "two", "three"}, "func", "var", 1) == "two" ); # check case insensitive +%!fail ('iptcheckstrs ("four", {"one", "two", "three"}, "func", "var", 1)'); # check failure if not found Added: trunk/octave-forge/main/image/inst/iptnum2ordinal.m =================================================================== --- trunk/octave-forge/main/image/inst/iptnum2ordinal.m (rev 0) +++ trunk/octave-forge/main/image/inst/iptnum2ordinal.m 2011-11-01 14:21:15 UTC (rev 8909) @@ -0,0 +1,96 @@ +## Copyright (C) 2011 Carnë Draug <car...@gm...> +## +## This program 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. +## +## This program 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 this program; if not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{ord} =} iptnum2ordinal (@var{num}) +## Convert number to ordinal string. +## +## @var{num} must be a real positive integer which will be converted to a string +## with its ordinal form @var{ord}. +## +## @example +## @group +## iptnum2ordinal (1) +## @result{} first +## iptnum2ordinal (12) +## @result{} twelfth +## iptnum2ordinal (21) +## @result{} 21st +## @end group +## @end example +## +## @seealso{num2str, sprintf, int2str, mat2str} +## @end deftypefn + +function ord = iptnum2ordinal (num) + + ## thanks to Skei in ##matlab for checking the grammar of ordinals and that it + ## is after number 20 that it starts using the suffixes only + + ## thanks to porten in ##matlab for help checking these corner-cases + ## the following were test and failed: Inf, 0, -1, 3.4, 1e-7 + ## using a string kind of succeeded as the character position in the ascii + ## table as used for the conversion + + if (nargin != 1) + print_usage; + elseif (!isnumeric (num) || !isscalar (num) || !isreal (num) || num <= 0 || rem (num, 1) != 0) + error ("num must be a real positive integer"); + endif + + switch num + case {1} ord = "first"; + case {2} ord = "second"; + case {3} ord = "third"; + case {4} ord = "fourth"; + case {5} ord = "fifth"; + case {6} ord = "sixth"; + case {7} ord = "seventh"; + case {8} ord = "eighth"; + case {9} ord = "ninth"; + case {10} ord = "tenth"; + case {11} ord = "eleventh"; + case {12} ord = "twelfth"; + case {13} ord = "thirteenth"; + case {14} ord = "fourteenth"; + case {15} ord = "fifteenth"; + case {16} ord = "sixteenth"; + case {17} ord = "seventeenth"; + case {18} ord = "eighteenth"; + case {19} ord = "nineteenth"; + case {20} ord = "twentieth"; + otherwise + ## if we ever want to mimic matlab's defective behaviour of accepting a + ## string and return the ordinal of position on the ascii table, we must + ## check here if it's a string, and if so, use: + ## ord = sprintf ("%dth", num); + num = num2str (num); + switch num(end) + case {"1"} ord = strcat (num, "st"); + case {"2"} ord = strcat (num, "nd"); + case {"3"} ord = strcat (num, "rd"); + otherwise ord = strcat (num, "th"); + endswitch + endswitch + +endfunction + +%!assert (strcmp (iptnum2ordinal (1), 'first')); # simple works +%!assert (strcmp (iptnum2ordinal (21), '21st')); # after 20, goes stupid +%!assert (strcmp (iptnum2ordinal (100), '100th')); # use th correctly +%!fail ("iptnum2ordinal (inf)"); # must be real +%!fail ("iptnum2ordinal (0)"); # must be positive +%!fail ("iptnum2ordinal (-1)"); # must be positive +%!fail ("iptnum2ordinal (3.4)"); # must be integer This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <car...@us...> - 2011-11-01 16:18:00
|
Revision: 8911 http://octave.svn.sourceforge.net/octave/?rev=8911&view=rev Author: carandraug Date: 2011-11-01 16:17:53 +0000 (Tue, 01 Nov 2011) Log Message: ----------- getrangefromclass: new function for image package Modified Paths: -------------- trunk/octave-forge/main/image/INDEX Added Paths: ----------- trunk/octave-forge/main/image/inst/getrangefromclass.m Modified: trunk/octave-forge/main/image/INDEX =================================================================== --- trunk/octave-forge/main/image/INDEX 2011-11-01 14:29:08 UTC (rev 8910) +++ trunk/octave-forge/main/image/INDEX 2011-11-01 16:17:53 UTC (rev 8911) @@ -110,6 +110,7 @@ stdfilt entropyfilt Utilities + getrangefromclass iptnum2ordinal iptcheckstrs iptchecknargin Added: trunk/octave-forge/main/image/inst/getrangefromclass.m =================================================================== --- trunk/octave-forge/main/image/inst/getrangefromclass.m (rev 0) +++ trunk/octave-forge/main/image/inst/getrangefromclass.m 2011-11-01 16:17:53 UTC (rev 8911) @@ -0,0 +1,68 @@ +## Copyright (C) 2011 Carnë Draug <car...@gm...> +## +## This program 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. +## +## This program 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 this program; if not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{range} =} getrangefromclass (@var{img}) +## Return display range of image. +## +## For a given image @var{img}, returns @var{range}, a 1x2 matrix with the +## minimum and maximum values. It supports the same classes as @code{intmax} and +## @code{intmin}, as well as 'logical', 'single', and 'double'. +## +## For @sc{matlab} compatibility, if @var{img} is of the class 'single' or +## 'double', min and max are considered 0 and 1 respectively. +## +## @example +## @group +## getrangefromclass (ones (5)) # note that class is 'double' +## @result{} [0 1] +## getrangefromclass (logical (ones (5))) +## @result{} [0 1] +## getrangefromclass (int8 (ones (5))) +## @result{} [-128 127] +## @end group +## @end example +## +## @seealso{intmin, intmax, bitmax} +## @end deftypefn + +function r = getrangefromclass (img) + + if (nargin != 1) + print_usage; + ## note that isnumeric would return false for logical matrix and ismatrix + ## returns true for strings + elseif (!ismatrix (img) || ischar (img)) + error ("Argument 'img' must be an image"); + endif + + cl = class (img); + if (regexp (cl, "u?int(8|16|32|64)")) + r = [intmin(cl) intmax(cl)]; + elseif (any (strcmp (cl, {"single", "double", "logical"}))) + r = [0 1]; + else + error ("Unknown class '%s'", cl) + endif + +endfunction + +%!assert (getrangefromclass (double (ones (5))) == [0 1]); # double returns [0 1] +%!assert (getrangefromclass (single (ones (5))) == [0 1]); # single returns [0 1] +%!assert (getrangefromclass (logical (ones (5))) == [0 1]); # logical returns [0 1] +%!assert (getrangefromclass (int8 (ones (5))) == [-128 127]); # checks int +%!assert (getrangefromclass (uint8 (ones (5))) == [0 255]); # checks unit +%!fail ("getrangefromclass ('string')"); # fails with strings +%!fail ("getrangefromclass ({3, 4})"); # fails with cells This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <car...@us...> - 2011-11-01 23:11:41
|
Revision: 8916 http://octave.svn.sourceforge.net/octave/?rev=8916&view=rev Author: carandraug Date: 2011-11-01 23:11:35 +0000 (Tue, 01 Nov 2011) Log Message: ----------- iptcheckconn: new image for image package Modified Paths: -------------- trunk/octave-forge/main/image/INDEX Added Paths: ----------- trunk/octave-forge/main/image/inst/iptcheckconn.m Modified: trunk/octave-forge/main/image/INDEX =================================================================== --- trunk/octave-forge/main/image/INDEX 2011-11-01 21:12:06 UTC (rev 8915) +++ trunk/octave-forge/main/image/INDEX 2011-11-01 23:11:35 UTC (rev 8916) @@ -111,7 +111,8 @@ entropyfilt Utilities getrangefromclass + iptcheckconn + iptcheckmap + iptchecknargin + iptcheckstrs iptnum2ordinal - iptcheckstrs - iptchecknargin - iptcheckmap Added: trunk/octave-forge/main/image/inst/iptcheckconn.m =================================================================== --- trunk/octave-forge/main/image/inst/iptcheckconn.m (rev 0) +++ trunk/octave-forge/main/image/inst/iptcheckconn.m 2011-11-01 23:11:35 UTC (rev 8916) @@ -0,0 +1,78 @@ +## Copyright (C) 2011 Carnë Draug <car...@gm...> +## +## This program 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. +## +## This program 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 this program; if not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {} iptcheckconn (@var{con}, @var{func_name}, @var{var_name}, @var{pos}) +## Check if argument is valid connectivity. +## +## If @var{con} is not a valid connectivity argument, gives a properly formatted +## error message. @var{func_name} is the name of the function to be used on the +## error message, @var{var_name} the name of the argument being checked (for the +## error message), and @var{pos} the position of the argument in the input. +## +## A valid connectivity argument must be either double or logical. It must also +## be either a scalar from set [1 4 6 8 18 26], or a symmetric matrix with all +## dimensions of size 3, with only 0 or 1 as values, and 1 at its center. +## +## @end deftypefn + +function iptcheckconn (con, func_name, var_name, pos) + + ## thanks to Oldak in ##matlab for checking the validity of connectivities + ## with more than 2D and the error messages + + if (nargin != 4) + print_usage; + elseif (!ischar (func_name)) + error ("Argument func_name must be a string"); + elseif (!ischar (var_name)) + error ("Argument var_name must be a string"); + elseif (!isnumeric (pos) || !isscalar (pos) || !isreal (pos) || pos <= 0 || rem (pos, 1) != 0) + error ("Argument pos must be a real positive integer"); + endif + + base_msg = sprintf ("Function %s expected input number %d, %s, to be a valid connectivity specifier.\n ", ... + func_name, pos, var_name); + + if (!any (strcmp (class (con), {'logical', 'double'})) || !isreal (con) || !isnumeric (con)) + error ("%sConnectivity must be a real number of the logical or double class.", base_msg); + elseif (isscalar (con)) + if (!any (con == [1 4 6 8 18 26])) + error ("%sIf connectivity is a scalar, must belong to the set [1 4 6 8 18 26].", base_msg); + endif + elseif (ismatrix (con)) + center_index = ceil(numel(con)/2); + if (any (size (con) != 3)) + error ("%sIf connectivity is a matrix, all dimensions must have size 3.", base_msg); + elseif (!all (con(:) == 1 | con(:) == 0)) + error ("%sIf connectivity is a matrix, only 0 and 1 are valid.", base_msg); + elseif (con(center_index) != 1) + error ("%sIf connectivity is a matrix, central element must be 1.", base_msg); + elseif (!all (con(1:center_index-1) == con(end:-1:center_index+1))) + error ("%sIf connectivity is a matrix, it must be symmetric relative to its center.", base_msg); + endif + else + error ("%s", base_msg); + endif + +endfunction + +%!test ("iptcheckconn (4, 'func', 'var', 2)"); # simple must work +%!test ("iptcheckconn (ones(3,3,3,3), 'func', 'var', 2)"); # accept more than just 3D +%!fail ("iptcheckconn (3, 'func', 'var', 2)"); # does not belong to set +%!fail ("iptcheckconn ([1 1 1; 1 0 1; 1 1 1], 'func', 'var', 2)"); # matrix center must be 1 +%!fail ("iptcheckconn ([1 2 1; 1 1 1; 1 1 1], 'func', 'var', 2)"); # matrix must be 1 and 0 only +%!fail ("iptcheckconn ([0 1 1; 1 1 1; 1 1 1], 'func', 'var', 2)"); # matrix must be symmetric +%!fail ("iptcheckconn (ones(3,3,3,4), 'func', 'var', 2)"); # matrix must have all sizes 3 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <car...@us...> - 2011-11-28 19:14:43
|
Revision: 9213 http://octave.svn.sourceforge.net/octave/?rev=9213&view=rev Author: carandraug Date: 2011-11-28 19:14:37 +0000 (Mon, 28 Nov 2011) Log Message: ----------- bwlabeln: added function to INDEX and MakeFile Modified Paths: -------------- trunk/octave-forge/main/image/INDEX trunk/octave-forge/main/image/src/Makefile Modified: trunk/octave-forge/main/image/INDEX =================================================================== --- trunk/octave-forge/main/image/INDEX 2011-11-28 19:13:38 UTC (rev 9212) +++ trunk/octave-forge/main/image/INDEX 2011-11-28 19:14:37 UTC (rev 9213) @@ -60,6 +60,7 @@ bweuler bwfill bwlabel + bwlabeln bwmorph bwperim bwselect Modified: trunk/octave-forge/main/image/src/Makefile =================================================================== --- trunk/octave-forge/main/image/src/Makefile 2011-11-28 19:13:38 UTC (rev 9212) +++ trunk/octave-forge/main/image/src/Makefile 2011-11-28 19:14:37 UTC (rev 9213) @@ -1,6 +1,6 @@ all: __spatial_filtering__.oct __bilateral__.oct __custom_gaussian_smoothing__.oct \ __boundary__.oct bwlabel.oct bwfill.oct rotate_scale.oct hough_line.oct \ - graycomatrix.oct deriche.oct __bwdist.oct nonmax_supress.oct + graycomatrix.oct deriche.oct __bwdist.oct nonmax_supress.oct bwlabeln.oct %.oct: %.cc mkoctfile -Wall $< This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <car...@us...> - 2011-12-09 05:24:12
|
Revision: 9320 http://octave.svn.sourceforge.net/octave/?rev=9320&view=rev Author: carandraug Date: 2011-12-09 05:24:05 +0000 (Fri, 09 Dec 2011) Log Message: ----------- image package: update NEWS and INDEX Modified Paths: -------------- trunk/octave-forge/main/image/INDEX trunk/octave-forge/main/image/NEWS Modified: trunk/octave-forge/main/image/INDEX =================================================================== --- trunk/octave-forge/main/image/INDEX 2011-12-09 05:15:25 UTC (rev 9319) +++ trunk/octave-forge/main/image/INDEX 2011-12-09 05:24:05 UTC (rev 9320) @@ -1,28 +1,13 @@ image >> Image processing -Display - rgbplot -Read/write - bmpwrite - readexif - tiff_tag_read -Reshape - imremap - imperspectivewarp - imresize - imrotate - imrotate_Fourier - imtranslate - imshear - impad - padarray - rotate_scale Analysis and Statistics + edge fftconv2 corr2 imhist mean2 std2 entropy + entropyfilt qtdecomp qtgetblk qtsetblk @@ -30,87 +15,103 @@ houghtf hough_line hough_circle - graythresh immaximas - phantom -Filtering - imfilter - colfilt - fspecial - imsmooth - histeq - imadjust - imnoise - medfilt2 - ordfilt2 - ordfiltn - uintlut - stretchlim - makelut applylut - deriche - radon - rho_filter - iradon - nonmax_supress + rangefilt + regionprops + stdfilt +Arithmetics + imadd + imcomplement Black and white image functions + applylut bwarea + bwborder bwboundaries bwconncomp bwdist bweuler bwfill + bwhitmiss bwlabel bwlabeln bwmorph bwperim bwselect - dilate - erode - bwborder edge - conndef - bwhitmiss - regionprops fchcode + makelut +Colour maps and Colour controls + cmpermute + cmunique + colorgradient + rgb2ycbcr +Display + rgbplot +Enhancement and Restoration + histeq + imadjust + imnoise + imsmooth + medfilt2 + ordfilt2 + ordfiltn + stretchlim +Filtering and Transforms + deriche + fspecial + imfilter + iradon + nonmax_supress + phantom + radon + rho_filter + uintlut Morhophological Operations + conndef + imbothat + imclose + imdilate imerode - imdilate imopen - imclose - imbothat imtophat mmgradm -Colour controls - cmpermute - cmunique - rgb2ycbcr -Representation - imdither +Read/write + bmpwrite + readexif + tiff_tag_read +Region-based and block processing + bestblk + blockproc + col2im + colfilt + im2col + nlfilter + poly2mask + roicolor +Spatial transformations + impad + imperspectivewarp + imremap + imresize + imrotate + imrotate_Fourier + imshear + imtranslate + rotate_scale +Types and Type conversions grayslice + graythresh im2bw im2double im2uint8 im2uint16 + imdither isbw isgray isind isrgb + label2rgb mat2gray rgb2gray - label2rgb - imcomplement -Colour maps - colorgradient -Region-based and block processing - roicolor - poly2mask - bestblk - blkproc - nlfilter - im2col - col2im - rangefilt - stdfilt - entropyfilt Utilities getrangefromclass iptcheckconn @@ -118,3 +119,4 @@ iptchecknargin iptcheckstrs iptnum2ordinal + padarray Modified: trunk/octave-forge/main/image/NEWS =================================================================== --- trunk/octave-forge/main/image/NEWS 2011-12-09 05:15:25 UTC (rev 9319) +++ trunk/octave-forge/main/image/NEWS 2011-12-09 05:24:05 UTC (rev 9320) @@ -3,8 +3,10 @@ ** The following functions are new: + blockproc bwlabeln getrangefromclass + imadd imbothat iptcheckconn iptcheckmap @@ -20,6 +22,7 @@ ** The following functions have been deprecated (see their help text for the recommended alternatives): + blkproc dilate erode This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <car...@us...> - 2011-12-09 19:19:06
|
Revision: 9346 http://octave.svn.sourceforge.net/octave/?rev=9346&view=rev Author: carandraug Date: 2011-12-09 19:19:00 +0000 (Fri, 09 Dec 2011) Log Message: ----------- imsubtract: new function Modified Paths: -------------- trunk/octave-forge/main/image/INDEX trunk/octave-forge/main/image/NEWS trunk/octave-forge/main/image/inst/imadd.m Added Paths: ----------- trunk/octave-forge/main/image/inst/imsubtract.m Modified: trunk/octave-forge/main/image/INDEX =================================================================== --- trunk/octave-forge/main/image/INDEX 2011-12-09 19:03:54 UTC (rev 9345) +++ trunk/octave-forge/main/image/INDEX 2011-12-09 19:19:00 UTC (rev 9346) @@ -22,6 +22,7 @@ Arithmetics imadd imcomplement + imsubtract Black and white image functions applylut bwarea Modified: trunk/octave-forge/main/image/NEWS =================================================================== --- trunk/octave-forge/main/image/NEWS 2011-12-09 19:03:54 UTC (rev 9345) +++ trunk/octave-forge/main/image/NEWS 2011-12-09 19:19:00 UTC (rev 9346) @@ -8,6 +8,7 @@ getrangefromclass imadd imbothat + imsubtract iptcheckconn iptcheckmap iptchecknargin Modified: trunk/octave-forge/main/image/inst/imadd.m =================================================================== --- trunk/octave-forge/main/image/inst/imadd.m 2011-12-09 19:03:54 UTC (rev 9345) +++ trunk/octave-forge/main/image/inst/imadd.m 2011-12-09 19:19:00 UTC (rev 9346) @@ -26,12 +26,13 @@ ## in which case @var{out} will be double. Alternatively, the class can be ## specified with @var{class}. ## -##@emph{Note 1}: you can force output class to be logical by specifying +## @emph{Note 1}: you can force output class to be logical by specifying ## @var{class}. This is incompatible with @sc{matlab} which will @emph{not} honour ## request to return a logical matrix. ## ## @emph{Note 2}: the values are truncated to the maximum value of the output ## class. +## @seealso{imsubtract} ## @end deftypefn function img = imadd (img, val, out_class = class (img)) Added: trunk/octave-forge/main/image/inst/imsubtract.m =================================================================== --- trunk/octave-forge/main/image/inst/imsubtract.m (rev 0) +++ trunk/octave-forge/main/image/inst/imsubtract.m 2011-12-09 19:19:00 UTC (rev 9346) @@ -0,0 +1,53 @@ +## Copyright (C) 2011 Carnë Draug <car...@gm...> +## +## This program 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. +## +## This program 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 this program; if not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{out} =} imsubtract (@var{a}, @var{b}) +## @deftypefnx {Function File} {@var{out} =} imsubtract (@var{a}, @var{b}, @var{class}) +## Subtract image or constant to an image. +## +## If @var{a} and @var{b} are two images of same size and class, @var{b} is subtracted +## to @var{a}. Alternatively, if @var{b} is a floating-point scalar, its value is subtracted +## to the image @var{a}. +## +## The class of @var{out} will be the same as @var{a} unless @var{a} is logical +## in which case @var{out} will be double. Alternatively, the class can be +## specified with @var{class}. +## +## @emph{Note 1}: you can force output class to be logical by specifying +## @var{class}. This is incompatible with @sc{matlab} which will @emph{not} honour +## request to return a logical matrix. +## +## @emph{Note 2}: the values are truncated to the mininum value of the output +## class. +## @seealso{imadd} +## @end deftypefn + +function img = imsubtract (img, val, out_class = class (img)) + + if (nargin < 2 || nargin > 3) + print_usage; + endif + [img, val] = imarithmetics ("imsubtract", img, val, out_class); + + ## The following makes the code imcompatible with matlab on certain cases. + ## This is on purpose. Read comments in imadd source for the reasons + if (nargin > 2 && strcmpi (out_class, "logical")) + img = img > val; + else + img = img - val; + endif + +endfunction This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <car...@us...> - 2011-12-10 19:50:31
|
Revision: 9353 http://octave.svn.sourceforge.net/octave/?rev=9353&view=rev Author: carandraug Date: 2011-12-10 19:50:25 +0000 (Sat, 10 Dec 2011) Log Message: ----------- imdivide immultiply: new functions Modified Paths: -------------- trunk/octave-forge/main/image/INDEX trunk/octave-forge/main/image/NEWS trunk/octave-forge/main/image/inst/imadd.m Added Paths: ----------- trunk/octave-forge/main/image/inst/imdivide.m trunk/octave-forge/main/image/inst/immultiply.m Modified: trunk/octave-forge/main/image/INDEX =================================================================== --- trunk/octave-forge/main/image/INDEX 2011-12-10 19:48:05 UTC (rev 9352) +++ trunk/octave-forge/main/image/INDEX 2011-12-10 19:50:25 UTC (rev 9353) @@ -22,6 +22,8 @@ Arithmetics imadd imcomplement + imdivide + immultiply imsubtract Black and white image functions applylut Modified: trunk/octave-forge/main/image/NEWS =================================================================== --- trunk/octave-forge/main/image/NEWS 2011-12-10 19:48:05 UTC (rev 9352) +++ trunk/octave-forge/main/image/NEWS 2011-12-10 19:50:25 UTC (rev 9353) @@ -8,6 +8,8 @@ getrangefromclass imadd imbothat + imdivide + immultiply imsubtract iptcheckconn iptcheckmap Modified: trunk/octave-forge/main/image/inst/imadd.m =================================================================== --- trunk/octave-forge/main/image/inst/imadd.m 2011-12-10 19:48:05 UTC (rev 9352) +++ trunk/octave-forge/main/image/inst/imadd.m 2011-12-10 19:50:25 UTC (rev 9353) @@ -32,7 +32,7 @@ ## ## @emph{Note 2}: the values are truncated to the maximum value of the output ## class. -## @seealso{imsubtract} +## @seealso{imdivide, imsubtract} ## @end deftypefn function img = imadd (img, val, out_class = class (img)) Added: trunk/octave-forge/main/image/inst/imdivide.m =================================================================== --- trunk/octave-forge/main/image/inst/imdivide.m (rev 0) +++ trunk/octave-forge/main/image/inst/imdivide.m 2011-12-10 19:50:25 UTC (rev 9353) @@ -0,0 +1,54 @@ +## Copyright (C) 2011 Carnë Draug <car...@gm...> +## +## This program 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. +## +## This program 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 this program; if not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{out} =} imdivide (@var{a}, @var{b}) +## @deftypefnx {Function File} {@var{out} =} imdivide (@var{a}, @var{b}, @var{class}) +## Divide image by another image or constant. +## +## If @var{a} and @var{b} are two images of same size and class, @var{a} is divided +## by @var{b}. Alternatively, if @var{b} is a floating-point scalar, @var{a} is divided +## by it. +## +## The class of @var{out} will be the same as @var{a} unless @var{a} is logical +## in which case @var{out} will be double. Alternatively, the class can be +## specified with @var{class}. +## +## @emph{Note}: the values are truncated to the mininum value of the output +## class. +## @seealso{imadd, imsubtract} +## @end deftypefn + +function img = imdivide (img, val, out_class = class (img)) + + if (nargin < 2 || nargin > 3) + print_usage; + endif + [img, val] = imarithmetics ("imdivide", img, val, out_class); + + ## matlab doesn't even gives a warning in this situation, it simply returns + ## a double precision float + if (nargin > 2 && strcmpi (out_class, "logical")) + warning ("Ignoring request to return logical as output of division."); + endif + + warn = warning ("query", "Octave:divide-by-zero"); + unwind_protect + img = img ./ val; + unwind_protect_cleanup + warning (warn.state, "Octave:divide-by-zero") + end_unwind_protect + +endfunction Added: trunk/octave-forge/main/image/inst/immultiply.m =================================================================== --- trunk/octave-forge/main/image/inst/immultiply.m (rev 0) +++ trunk/octave-forge/main/image/inst/immultiply.m 2011-12-10 19:50:25 UTC (rev 9353) @@ -0,0 +1,49 @@ +## Copyright (C) 2011 Carnë Draug <car...@gm...> +## +## This program 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. +## +## This program 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 this program; if not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{out} =} immultiply (@var{a}, @var{b}) +## @deftypefnx {Function File} {@var{out} =} immultiply (@var{a}, @var{b}, @var{class}) +## Multiply image by another image or constant. +## +## If @var{a} and @var{b} are two images of same size and class, the images are +## multiplied. Alternatively, if @var{b} is a floating-point scalar, @var{a} is +## multiplie by it. +## +## The class of @var{out} will be the same as @var{a} unless @var{a} is logical +## in which case @var{out} will be double. Alternatively, the class can be +## specified with @var{class}. +## +## @emph{Note}: the values are truncated to the mininum value of the output +## class. +## @seealso{imadd, imsubtract} +## @end deftypefn + +function img = immultiply (img, val, out_class = class (img)) + + if (nargin < 2 || nargin > 3) + print_usage; + endif + [img, val] = imarithmetics ("immultiply", img, val, out_class); + + ## matlab doesn't even gives a warning in this situation, it simply returns + ## a double precision float + if (nargin > 2 && strcmpi (out_class, "logical")) + warning ("Ignoring request to return logical as output of multiplication."); + endif + + img = img .* val; + +endfunction This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <car...@us...> - 2012-04-11 18:23:15
|
Revision: 10196 http://octave.svn.sourceforge.net/octave/?rev=10196&view=rev Author: carandraug Date: 2012-04-11 18:23:09 +0000 (Wed, 11 Apr 2012) Log Message: ----------- im2uint8: matlab compatibility and support for indexed images Modified Paths: -------------- trunk/octave-forge/main/image/NEWS trunk/octave-forge/main/image/inst/im2uint16.m trunk/octave-forge/main/image/inst/im2uint8.m Modified: trunk/octave-forge/main/image/NEWS =================================================================== --- trunk/octave-forge/main/image/NEWS 2012-04-11 17:51:21 UTC (rev 10195) +++ trunk/octave-forge/main/image/NEWS 2012-04-11 18:23:09 UTC (rev 10196) @@ -44,6 +44,7 @@ imhist conndef im2double + im2uint8 im2uint16 isbw isgray Modified: trunk/octave-forge/main/image/inst/im2uint16.m =================================================================== --- trunk/octave-forge/main/image/inst/im2uint16.m 2012-04-11 17:51:21 UTC (rev 10195) +++ trunk/octave-forge/main/image/inst/im2uint16.m 2012-04-11 18:23:09 UTC (rev 10196) @@ -45,7 +45,7 @@ ## do nothing, return the same case {"single", "double"} if (indexed) - imax = max( im(:)); + imax = max (im(:)); if ( imax > intmax ("uint16")) error ("Too many colors '%d' for an indexed uint16 image", imax); endif Modified: trunk/octave-forge/main/image/inst/im2uint8.m =================================================================== --- trunk/octave-forge/main/image/inst/im2uint8.m 2012-04-11 17:51:21 UTC (rev 10195) +++ trunk/octave-forge/main/image/inst/im2uint8.m 2012-04-11 18:23:09 UTC (rev 10196) @@ -1,47 +1,83 @@ -## Copyright (C) 2007 S\xF8ren Hauberg -## -## This program 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 2, or (at your option) -## any later version. -## -## This program 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 this file. If not, see <http://www.gnu.org/licenses/>. +## Copyright (C) 2007 S\xF8ren Hauberg <so...@ha...> +## Copyright (C) 2012 Carn\xEB Draug <car...@gm...> +## +## This program 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. +## +## This program 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 +## this program; if not, see <http://www.gnu.org/licenses/>. ## -*- texinfo -*- -## @deftypefn {Function File} @var{im2} = im2uint8(@var{im1}) -## Converts the input image to an image of class uint8. +## @deftypefn {Function File} @var{im2} = im2uint8 (@var{im1}) +## @deftypefnx {Function File} @var{im2} = im2uint8 (@var{im1}, "indexed") +## Convert input image @var{im1} to uint16 precision. ## -## If the input image is of class uint8 the output is unchanged. -## If the input is of class double the result will be multiplied -## by 255 and converted to uint8, and if the input is of class uint16 the -## image will be divided by 257 and converted to uint8. +## The following images type are supported: double, single, uint8, uint16, int16, +## binary (logical), indexed. If @var{im1} is an indexed images, the second +## argument must be a string with the value `indexed'. +## +## Processing will depend on the class of the input image @var{im1}: +## @itemize @bullet +## @item uint8 - returns the same as input +## @item uint16, double, single, int16, logical - output will be rescaled for the +## interval of the uint8 class [0 255] +## @item indexed - depends on the input class. No value can be above the max of +## the uint8 class (255). +## @end itemize +## ## @seealso{im2bw, im2uint16, im2double} ## @end deftypefn -function im2 = im2uint8(im1) - ## Input checking - if (nargin < 1) - print_usage(); +function im = im2uint8 (im, indexed = false) + + ## Input checking (private function that is used for all im2class functions) + im_class = imconversion (nargin, "im2uint8", indexed, im); + + if (indexed) + imax = max (im(:)); + if (imax > intmax ("uint8")) + error ("Too many colors '%d' for an indexed uint8 image", imax); + endif endif - if (!isgray(im1) && !isrgb(im1)) - error("im2uint8: input must be an image"); - endif - - ## Take action depending on the class of the data - switch (class(im1)) - case "double" - im2 = uint8(255*im1); + + switch im_class case "uint8" - im2 = im1; + ## do nothing, return the same + case {"single", "double"} + if (indexed) + im = uint8 (im) - 1; + else + im = uint8 (im * double (intmax ("uint8"))); + endif + case "logical" + im = uint8 (im) * intmax ("uint8"); case "uint16" - im2 = uint8(im1/257); + if (indexed) + im = uint8 (im); + else + ## 257 is the ratio between the max of uint8 and uint16 + ## double (intmax ("uint16")) / double (intmax ("uint8")) == 257 + im = uint8 (im / 257); + endif + case "int16" + im = uint8 ((double (im) + double (intmax (im_class)) + 1) / 257); otherwise - error("im2uint8: unsupported image class"); + error ("unsupported image class %s", im_class); endswitch + endfunction + +%!assert(im2uint8(uint8([1 2 3])), uint8([1 2 3])); # uint16 returns the same +%!assert(im2uint8(uint16([0 65535])), uint8([0 255])); # basic usage with uint16 +%!assert(im2uint8([0 0.5 1]), uint8([0 128 255])); # basic usage with double +%!assert(im2uint8([1 2]), uint8([255 255])); # for double, above 1 is same as 1 +%!assert(im2uint8(uint16([3 25]), "indexed"), uint8([3 25])); # test indexed uint8 +%!assert(im2uint8([3 25], "indexed"), uint8([2 24])); # test indexed double +%!assert(im2uint8(int16([-32768 0 32768])), uint8([0 128 255])); # test signed integer This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <car...@us...> - 2011-12-10 23:37:05
|
Revision: 9361 http://octave.svn.sourceforge.net/octave/?rev=9361&view=rev Author: carandraug Date: 2011-12-10 23:36:58 +0000 (Sat, 10 Dec 2011) Log Message: ----------- imabsdiff: new function Modified Paths: -------------- trunk/octave-forge/main/image/INDEX trunk/octave-forge/main/image/NEWS trunk/octave-forge/main/image/inst/imadd.m trunk/octave-forge/main/image/inst/imdivide.m trunk/octave-forge/main/image/inst/immultiply.m trunk/octave-forge/main/image/inst/imsubtract.m Added Paths: ----------- trunk/octave-forge/main/image/inst/imabsdiff.m Modified: trunk/octave-forge/main/image/INDEX =================================================================== --- trunk/octave-forge/main/image/INDEX 2011-12-10 23:34:33 UTC (rev 9360) +++ trunk/octave-forge/main/image/INDEX 2011-12-10 23:36:58 UTC (rev 9361) @@ -20,6 +20,7 @@ regionprops stdfilt Arithmetics + imabsdiff imadd imcomplement imdivide Modified: trunk/octave-forge/main/image/NEWS =================================================================== --- trunk/octave-forge/main/image/NEWS 2011-12-10 23:34:33 UTC (rev 9360) +++ trunk/octave-forge/main/image/NEWS 2011-12-10 23:36:58 UTC (rev 9361) @@ -6,6 +6,7 @@ blockproc bwlabeln getrangefromclass + imabsdiff imadd imbothat imdivide Added: trunk/octave-forge/main/image/inst/imabsdiff.m =================================================================== --- trunk/octave-forge/main/image/inst/imabsdiff.m (rev 0) +++ trunk/octave-forge/main/image/inst/imabsdiff.m 2011-12-10 23:36:58 UTC (rev 9361) @@ -0,0 +1,64 @@ +## Copyright (C) 2011 Carnë Draug <car...@gm...> +## +## This program 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. +## +## This program 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 this program; if not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{out} =} imabsdiff (@var{a}, @var{b}) +## @deftypefnx {Function File} {@var{out} =} imabsdiff (@var{a}, @var{b}, @var{class}) +## Return absolute difference of image or constant to an image. +## +## If @var{a} and @var{b} are two images of same size and class, returns the absolute +## difference between @var{b} and @var{a}. +## +## The class of @var{out} will be the same as @var{a} unless @var{a} is logical +## in which case @var{out} will be double. Alternatively, the class can be +## specified with @var{class}. +## +## @emph{Note 1}: you can force output class to be logical by specifying +## @var{class}. This is incompatible with @sc{matlab} which will @emph{not} honour +## request to return a logical matrix. +## +## @emph{Note 2}: the values are truncated to the mininum value of the output +## class. +## @seealso{imadd, imcomplement, imdivide, immultiply, imsubtract} +## @end deftypefn + +function img = imabsdiff (img, val, out_class = class (img)) + + if (nargin < 2 || nargin > 3) + print_usage; + endif + + ## we want to make subtraction as double so this is it + [img, val] = imarithmetics ("imabsdiff", img, val, "double"); + converter = str2func (tolower (out_class)); + + if (nargin < 3 && strcmp (out_class, "logical")) + ## it is using logical as default. Use double instead. We only have this + ## problem on this function because we are are not actually giving out_class + ## to imarithmetics + converter = @double; + else + converter = str2func (tolower (out_class)); + endif + img = converter (abs (img - val)); + +endfunction + +%!assert (imabsdiff (uint8 ([23 250]), uint8 ([26 50])), uint8 ([ 3 200])); # default to first class and abs works +%!assert (imabsdiff (uint8 ([23 250]), uint8 ([24 50]), "uint16"), uint16 ([ 1 200])); # defining output class works (not in matlab) +%!assert (imabsdiff (uint8 ([23 250]), uint8 ([24 255]), "int8"), int8 ([ 1 5])); # signed integers kinda work (not in matlab) +%!assert (imabsdiff (logical ([ 1 0]), logical ([ 1 1])), double ([ 0 1])); # return double for two logical images +%!fail ("imabsdiff (uint8 ([23 250]), 30"); # fails subtracting a scalar +%!fail ("imabsdiff (uint8 ([23 250]), uint16 ([23 250]))"); # input need to have same class Modified: trunk/octave-forge/main/image/inst/imadd.m =================================================================== --- trunk/octave-forge/main/image/inst/imadd.m 2011-12-10 23:34:33 UTC (rev 9360) +++ trunk/octave-forge/main/image/inst/imadd.m 2011-12-10 23:36:58 UTC (rev 9361) @@ -32,7 +32,7 @@ ## ## @emph{Note 2}: the values are truncated to the maximum value of the output ## class. -## @seealso{imcomplement, imdivide, immultiply, imsubtract} +## @seealso{imabsdiff, imcomplement, imdivide, immultiply, imsubtract} ## @end deftypefn function img = imadd (img, val, out_class = class (img)) @@ -70,4 +70,4 @@ %!assert (imadd (uint8 ([23 250]), uint8 ([23 250]), "uint16"), uint16 ([46 500])); # defining output class works %!assert (imadd (logical ([ 1 0]), logical ([ 1 1])), double ([ 2 1])); # return double for two logical images %!assert (imadd (logical ([ 1 0]), logical ([ 1 1]), "logical"), logical ([ 1 1])); # this is matlab incompatible on purpose -%!fail ("imadd (uint8 ([23 250]), uint16 ([23 250]))") # input need to have same class +%!fail ("imadd (uint8 ([23 250]), uint16 ([23 250]))"); # input need to have same class Modified: trunk/octave-forge/main/image/inst/imdivide.m =================================================================== --- trunk/octave-forge/main/image/inst/imdivide.m 2011-12-10 23:34:33 UTC (rev 9360) +++ trunk/octave-forge/main/image/inst/imdivide.m 2011-12-10 23:36:58 UTC (rev 9361) @@ -28,7 +28,7 @@ ## ## @emph{Note}: the values are truncated to the mininum value of the output ## class. -## @seealso{imadd, imcomplement, immultiply, imsubtract} +## @seealso{imabsdiff, imadd, imcomplement, immultiply, imsubtract} ## @end deftypefn function img = imdivide (img, val, out_class = class (img)) @@ -58,4 +58,4 @@ %!assert (imdivide (uint8 ([23 250]), 2), uint8 ([ 12 125])); # works subtracting a scalar %!assert (imdivide (uint8 ([23 250]), uint8 ([ 2 50]), "uint16"), uint16 ([ 12 5])); # defining output class works (not in matlab) %!assert (imdivide (logical ([1 1 0 0]), logical ([1 0 1 0])), double ([1 Inf 0 NaN])); # dividing logical matrix (tested in matlab) -%!fail ("imdivide (uint8 ([23 250]), uint16 ([23 250]))") # input needs to have same class +%!fail ("imdivide (uint8 ([23 250]), uint16 ([23 250]))"); # input needs to have same class Modified: trunk/octave-forge/main/image/inst/immultiply.m =================================================================== --- trunk/octave-forge/main/image/inst/immultiply.m 2011-12-10 23:34:33 UTC (rev 9360) +++ trunk/octave-forge/main/image/inst/immultiply.m 2011-12-10 23:36:58 UTC (rev 9361) @@ -28,7 +28,7 @@ ## ## @emph{Note}: the values are truncated to the mininum value of the output ## class. -## @seealso{imadd, imcomplement, imdivide, imsubtract} +## @seealso{imabsdiff, imadd, imcomplement, imdivide, imsubtract} ## @end deftypefn function img = immultiply (img, val, out_class = class (img)) Modified: trunk/octave-forge/main/image/inst/imsubtract.m =================================================================== --- trunk/octave-forge/main/image/inst/imsubtract.m 2011-12-10 23:34:33 UTC (rev 9360) +++ trunk/octave-forge/main/image/inst/imsubtract.m 2011-12-10 23:36:58 UTC (rev 9361) @@ -46,7 +46,7 @@ ## ## Because both 190 and 200 were truncated to 127 before subtraction, their difference ## is zero. -## @seealso{imadd, imcomplement, imdivide, immultiply} +## @seealso{imabsdiff, imadd, imcomplement, imdivide, immultiply} ## @end deftypefn function img = imsubtract (img, val, out_class = class (img)) @@ -80,4 +80,4 @@ %!assert (imsubtract (uint8 ([23 250]), uint8 ([24 255]), "int8"), int8 ([-1 0])); # signed integers kinda work (not in matlab) %!assert (imsubtract (logical ([ 1 0]), logical ([ 1 1])), double ([ 0 -1])); # return double for two logical images %!assert (imsubtract (logical ([ 1 0]), logical ([ 1 1]), "logical"), logical ([ 0 0])); # this is matlab incompatible on purpose -%!fail ("imsubtract (uint8 ([23 250]), uint16 ([23 250]))") # input need to have same class +%!fail ("imsubtract (uint8 ([23 250]), uint16 ([23 250]))"); # input need to have same class This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <car...@us...> - 2011-12-11 03:30:47
|
Revision: 9363 http://octave.svn.sourceforge.net/octave/?rev=9363&view=rev Author: carandraug Date: 2011-12-11 03:30:40 +0000 (Sun, 11 Dec 2011) Log Message: ----------- imlincomb: new function Modified Paths: -------------- trunk/octave-forge/main/image/INDEX trunk/octave-forge/main/image/NEWS trunk/octave-forge/main/image/inst/imabsdiff.m trunk/octave-forge/main/image/inst/imadd.m trunk/octave-forge/main/image/inst/imcomplement.m trunk/octave-forge/main/image/inst/imdivide.m trunk/octave-forge/main/image/inst/immultiply.m trunk/octave-forge/main/image/inst/imsubtract.m Added Paths: ----------- trunk/octave-forge/main/image/inst/imlincomb.m Modified: trunk/octave-forge/main/image/INDEX =================================================================== --- trunk/octave-forge/main/image/INDEX 2011-12-11 03:30:06 UTC (rev 9362) +++ trunk/octave-forge/main/image/INDEX 2011-12-11 03:30:40 UTC (rev 9363) @@ -24,6 +24,7 @@ imadd imcomplement imdivide + imlincomb immultiply imsubtract Black and white image functions Modified: trunk/octave-forge/main/image/NEWS =================================================================== --- trunk/octave-forge/main/image/NEWS 2011-12-11 03:30:06 UTC (rev 9362) +++ trunk/octave-forge/main/image/NEWS 2011-12-11 03:30:40 UTC (rev 9363) @@ -10,6 +10,7 @@ imadd imbothat imdivide + imlincomb immultiply imsubtract iptcheckconn Modified: trunk/octave-forge/main/image/inst/imabsdiff.m =================================================================== --- trunk/octave-forge/main/image/inst/imabsdiff.m 2011-12-11 03:30:06 UTC (rev 9362) +++ trunk/octave-forge/main/image/inst/imabsdiff.m 2011-12-11 03:30:40 UTC (rev 9363) @@ -31,7 +31,7 @@ ## ## @emph{Note 2}: the values are truncated to the mininum value of the output ## class. -## @seealso{imadd, imcomplement, imdivide, immultiply, imsubtract} +## @seealso{imadd, imcomplement, imdivide, imlincomb, immultiply, imsubtract} ## @end deftypefn function img = imabsdiff (img, val, out_class = class (img)) Modified: trunk/octave-forge/main/image/inst/imadd.m =================================================================== --- trunk/octave-forge/main/image/inst/imadd.m 2011-12-11 03:30:06 UTC (rev 9362) +++ trunk/octave-forge/main/image/inst/imadd.m 2011-12-11 03:30:40 UTC (rev 9363) @@ -32,7 +32,7 @@ ## ## @emph{Note 2}: the values are truncated to the maximum value of the output ## class. -## @seealso{imabsdiff, imcomplement, imdivide, immultiply, imsubtract} +## @seealso{imabsdiff, imcomplement, imdivide, imlincomb, immultiply, imsubtract} ## @end deftypefn function img = imadd (img, val, out_class = class (img)) Modified: trunk/octave-forge/main/image/inst/imcomplement.m =================================================================== --- trunk/octave-forge/main/image/inst/imcomplement.m 2011-12-11 03:30:06 UTC (rev 9362) +++ trunk/octave-forge/main/image/inst/imcomplement.m 2011-12-11 03:30:40 UTC (rev 9363) @@ -21,7 +21,7 @@ ## For binary images, the complement is computed as @code{!@var{A}}, for floating ## point images it is computed as @code{1 - @var{A}}, and for integer images as ## @code{intmax(class(@var{A})) - @var{A}}. -## @seealso{imadd, imdivide, immultiply, imsubtract} +## @seealso{imadd, imdivide, imlincomb, immultiply, imsubtract} ## @end deftypefn function B = imcomplement(A) Modified: trunk/octave-forge/main/image/inst/imdivide.m =================================================================== --- trunk/octave-forge/main/image/inst/imdivide.m 2011-12-11 03:30:06 UTC (rev 9362) +++ trunk/octave-forge/main/image/inst/imdivide.m 2011-12-11 03:30:40 UTC (rev 9363) @@ -28,7 +28,7 @@ ## ## @emph{Note}: the values are truncated to the mininum value of the output ## class. -## @seealso{imabsdiff, imadd, imcomplement, immultiply, imsubtract} +## @seealso{imabsdiff, imadd, imcomplement, immultiply, imlincomb, imsubtract} ## @end deftypefn function img = imdivide (img, val, out_class = class (img)) Added: trunk/octave-forge/main/image/inst/imlincomb.m =================================================================== --- trunk/octave-forge/main/image/inst/imlincomb.m (rev 0) +++ trunk/octave-forge/main/image/inst/imlincomb.m 2011-12-11 03:30:40 UTC (rev 9363) @@ -0,0 +1,90 @@ +## Copyright (C) 2011 Carnë Draug <car...@gm...> +## +## This program 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. +## +## This program 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 this program; if not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{out} =} imlincomb (@var{fac}, @var{img}) +## @deftypefnx {Function File} {@var{out} =} imlincomb (@var{fac1}, @var{img1}, @var{fac2}, @var{img2}, @dots{}) +## @deftypefnx {Function File} {@var{out} =} imlincomb (@dots{}, @var{class}) +## Combine images linearly. +## +## Returns the computed image as per: +## +## @var{out} = @var{fac}1*@var{img}1 + @var{fac}2*@var{img}2 + @dots{} + @var{fac}n*@var{img}n +## +## The images @var{img}1..n must all be of same size and class. The factors @var{fac}1..n +## must all be floating-point scalars. +## +## The class of @var{out} will be the same as @var{img}s unless @var{img}s are logical +## in which case @var{out} will be double. Alternatively, it can be specified +## with @var{class}. +## +## If applying several arithmetic operations on images, @code{imlincomb} is more +## precise since calculations are performed at double precision. +## +## @emph{Note 1}: you can force output class to be logical by specifying +## @var{class} though it possibly doesn't make a lot of sense. +## +## @seealso{imadd, imcomplement, imdivide, immultiply, imsubtract} +## @end deftypefn + +function out = imlincomb (varargin) + + if (nargin < 2) + print_usage; + else + if (rem (nargin, 2) == 0) + ## use default for output class; the class of first image (second argument) + out_class = class (varargin{2}); + def_class = true; + else + ## last argument is requested output class + out_class = varargin{end}; + def_class = false; + endif + endif + + facI = 1:2:nargin-1; # index for factors + imgI = 2:2:nargin; # index for images + imgC = class (varargin{2}); # class of the first image + + out = zeros (size (varargin{2})); + for i = 1:numel (imgI) + ## we keep index the images froom varargin rather than copying to new variable to + ## avoid taking up a lot of memory + if (!isreal (varargin{facI(i)}) || !isscalar (varargin{facI(i)}) || !isfloat (varargin{facI(i)})) + error ("factor to multiply each image must be a real, floating-point, scalar."); + elseif ((!isnumeric (varargin{imgI(i)}) && !islogical (varargin{imgI(i)})) ... + || isempty (varargin{imgI(i)}) || issparse (varargin{imgI(i)}) ... + || !isreal (varargin{imgI(i)}) || !isa (varargin{imgI(i)}, imgC)) + error ("images must be a numeric or logical, non-empty, non-sparse real matrix of the same class."); + endif + img = double(varargin{imgI(i)}) .* double(varargin{facI(i)}); + out += img; + endfor + + ## this is probably matlab imcompatible since by their documentation, they don't even + ## support logical matrix. If specified by user, respect and return a logical + ## matrix. Otherwise, return a double, even if images were all logical + if (strcmpi (out_class, "logical") && def_class) + cnv = @double; + else + cnv = str2func (tolower (out_class)); + endif + out = cnv (out); + +endfunction + +%!assert (imlincomb (0.5, uint8 ([255 10]), 0.5, uint8 ([50 20])), uint8 ([153 15])); # default to first class and truncate +%!assert (imlincomb (0.5, uint8 ([255 10]), 0.5, uint8 ([50 20]), "uint16"), uint16 ([153 15])); # defining output class works Modified: trunk/octave-forge/main/image/inst/immultiply.m =================================================================== --- trunk/octave-forge/main/image/inst/immultiply.m 2011-12-11 03:30:06 UTC (rev 9362) +++ trunk/octave-forge/main/image/inst/immultiply.m 2011-12-11 03:30:40 UTC (rev 9363) @@ -28,7 +28,7 @@ ## ## @emph{Note}: the values are truncated to the mininum value of the output ## class. -## @seealso{imabsdiff, imadd, imcomplement, imdivide, imsubtract} +## @seealso{imabsdiff, imadd, imcomplement, imdivide, imlincomb, imsubtract} ## @end deftypefn function img = immultiply (img, val, out_class = class (img)) Modified: trunk/octave-forge/main/image/inst/imsubtract.m =================================================================== --- trunk/octave-forge/main/image/inst/imsubtract.m 2011-12-11 03:30:06 UTC (rev 9362) +++ trunk/octave-forge/main/image/inst/imsubtract.m 2011-12-11 03:30:40 UTC (rev 9363) @@ -46,7 +46,7 @@ ## ## Because both 190 and 200 were truncated to 127 before subtraction, their difference ## is zero. -## @seealso{imabsdiff, imadd, imcomplement, imdivide, immultiply} +## @seealso{imabsdiff, imadd, imcomplement, imdivide, imlincomb, immultiply} ## @end deftypefn function img = imsubtract (img, val, out_class = class (img)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <car...@us...> - 2011-12-16 20:33:15
|
Revision: 9415 http://octave.svn.sourceforge.net/octave/?rev=9415&view=rev Author: carandraug Date: 2011-12-16 20:33:08 +0000 (Fri, 16 Dec 2011) Log Message: ----------- normxcorr2: new function is wrapper for xcorr2 from signal package Modified Paths: -------------- trunk/octave-forge/main/image/DESCRIPTION trunk/octave-forge/main/image/INDEX trunk/octave-forge/main/image/NEWS Added Paths: ----------- trunk/octave-forge/main/image/inst/normxcorr2.m Modified: trunk/octave-forge/main/image/DESCRIPTION =================================================================== --- trunk/octave-forge/main/image/DESCRIPTION 2011-12-16 20:32:15 UTC (rev 9414) +++ trunk/octave-forge/main/image/DESCRIPTION 2011-12-16 20:33:08 UTC (rev 9415) @@ -9,7 +9,7 @@ The package also provides functions for feature extraction, image statistics, spatial and geometric transformations, morphological operations, linear filtering, and much more. -Depends: octave (>= 3.4.0) +Depends: octave (>= 3.4.0), signal Autoload: yes License: GPL version 2 or later Url: http://octave.sf.net Modified: trunk/octave-forge/main/image/INDEX =================================================================== --- trunk/octave-forge/main/image/INDEX 2011-12-16 20:32:15 UTC (rev 9414) +++ trunk/octave-forge/main/image/INDEX 2011-12-16 20:33:08 UTC (rev 9415) @@ -16,6 +16,7 @@ hough_line hough_circle immaximas + normxcorr2 rangefilt regionprops stdfilt Modified: trunk/octave-forge/main/image/NEWS =================================================================== --- trunk/octave-forge/main/image/NEWS 2011-12-16 20:32:15 UTC (rev 9414) +++ trunk/octave-forge/main/image/NEWS 2011-12-16 20:33:08 UTC (rev 9415) @@ -18,6 +18,7 @@ iptchecknargin iptcheckstrs iptnum2ordinal + normxcorr2 ** The following functions have been deprecated in previous releases of the image package and have now been removed: Added: trunk/octave-forge/main/image/inst/normxcorr2.m =================================================================== --- trunk/octave-forge/main/image/inst/normxcorr2.m (rev 0) +++ trunk/octave-forge/main/image/inst/normxcorr2.m 2011-12-16 20:33:08 UTC (rev 9415) @@ -0,0 +1,31 @@ +## Copyright (C) 2011 Carnë Draug <car...@gm...> +## +## This program 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. +## +## This program 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 this program; if not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{cc} =} normxcorr2 (@var{template}, @var{img}) +## @deftypefn {Function File} {@var{cc} =} normxcorr2 (@var{template}, @var{img}) +## Compute the normalized 2D cross correlation. +## +## The output matrix @var{cc} shows the correlation coefficients of @var{template} +## for each position in @var{img}. +## @seealso{conv2, corr2, xcorr2} +## @end deftypefn + +function cc = normxcorr2 (temp, img) + if (nargin != 2) + print_usage; + endif + cc = xcorr2 (img, temp, "coeff"); +endfunction This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <car...@us...> - 2012-01-27 16:42:00
|
Revision: 9570 http://octave.svn.sourceforge.net/octave/?rev=9570&view=rev Author: carandraug Date: 2012-01-27 16:41:53 +0000 (Fri, 27 Jan 2012) Log Message: ----------- wavelength: new function to image package. Contributed by William Krekeler <WKr...@cl...> Modified Paths: -------------- trunk/octave-forge/main/image/INDEX trunk/octave-forge/main/image/NEWS Added Paths: ----------- trunk/octave-forge/main/image/inst/wavelength2rgb.m Modified: trunk/octave-forge/main/image/INDEX =================================================================== --- trunk/octave-forge/main/image/INDEX 2012-01-26 19:55:15 UTC (rev 9569) +++ trunk/octave-forge/main/image/INDEX 2012-01-27 16:41:53 UTC (rev 9570) @@ -50,6 +50,7 @@ cmunique colorgradient rgb2ycbcr + wavelength2rgb Display rgbplot Enhancement and Restoration Modified: trunk/octave-forge/main/image/NEWS =================================================================== --- trunk/octave-forge/main/image/NEWS 2012-01-26 19:55:15 UTC (rev 9569) +++ trunk/octave-forge/main/image/NEWS 2012-01-27 16:41:53 UTC (rev 9570) @@ -19,6 +19,7 @@ iptcheckstrs iptnum2ordinal normxcorr2 + wavelength2rgb ** The following functions have been deprecated in previous releases of the image package and have now been removed: Added: trunk/octave-forge/main/image/inst/wavelength2rgb.m =================================================================== --- trunk/octave-forge/main/image/inst/wavelength2rgb.m (rev 0) +++ trunk/octave-forge/main/image/inst/wavelength2rgb.m 2012-01-27 16:41:53 UTC (rev 9570) @@ -0,0 +1,132 @@ +## Copyright (C) 2011 William Krekeler <WKr...@cl...> +## +## This program 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. +## +## This program 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 +## this program; if not, see <http://www.gnu.org/licenses/>. + +function RGB = wavelength2rgb( WAVELENGTH, varargin) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% function RGB = wavelength2rgb( WAVELENGTH, <INTENSITY_MAX>, <GAMMA> ) +% +% Author: William Krekeler +% Date : 20111031 +% Synopsis: convert wavelength in nm into an RGB value set +% +% Returns: RGB value set on scale of 1:INTENSITY_MAX +% +% Variables: +% all variables encoded as <VAR> are optional, +% +% WAVELENGTH = wavelength of input light value in nm +% value can not be a vector +% +% INTENSITY_MAX = ( default = 255 ) max of integer scale to output values in +% +% GAMMA = ( default = 0.8 ); value should be 0-1. Controls luminance +% +% Example Calls: +% +% X = 350:0.5:800; +% Y = exp(log(X.^3)); % arbitrary +% figure, plot( X, Y ) +% stepSize = .5*max(diff( X ) ); +% for n = 1:numel(Y) +% RGB = wavelength2rgb( X(n), 1 ); +% if ( sum( RGB ) > 0 ) % ie don't fill black +% hold on, area( (X(n)-stepSize):(stepSize/1):(X(n)+stepSize), ... +% repmat( Y(n), 1, numel((X(n)-stepSize):(stepSize/1):(X(n)+stepSize)) ), ... +% 'EdgeColor', RGB, 'FaceColor', RGB ); hold off +% end +% end +% +% Version Update: 20111031 (created) +% +% See also: +% put in src +% +% Source: +% http://stackoverflow.com/questions/2374959/algorithm-to-convert-any-positive-integer-to-an-rgb-value +% http://www.midnightkite.com/color.html per Dan Bruton +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% -- handle inputs +optargin = size( varargin, 2 ); + +% set Intensity Max +if ( optargin > 0 ) + INTENSITY_MAX = cell2mat(varargin(1)); +else + INTENSITY_MAX = 255; +end + +% set the GAMMA value +if ( optargin > 1 ) + GAMMA = cell2mat(varargin(2)); +else + GAMMA = 0.80; +end + +if ( GAMMA > 1 || GAMMA < 0 ) + GAMMA = 0.80; +end + +RGB = zeros(3, numel(WAVELENGTH) ); % initialize RGB, each RGB set stored by column + +% set the factor +if ( WAVELENGTH >= 380 && WAVELENGTH < 420 ) + factor = 0.3 + 0.7*(WAVELENGTH - 380) / (420 - 380); +elseif ( WAVELENGTH >= 420 && WAVELENGTH < 701 ) + factor = 1; +elseif ( WAVELENGTH >= 420 && WAVELENGTH < 701 ) + factor = 0.3 + 0.7*(780 - WAVELENGTH) / (780 - 700); +else + factor = 0; +end + +% initialize RGB +if ( WAVELENGTH >=380 && WAVELENGTH < 440 ) + RGB(1) = -(WAVELENGTH - 440) / (440 - 380); + RGB(2) = 0.0; + RGB(3) = 1.0; +elseif ( WAVELENGTH >= 440 && WAVELENGTH < 490 ) + RGB(1) = 0.0; + RGB(2) = (WAVELENGTH - 440) / (490 - 440); + RGB(3) = 1.0; +elseif ( WAVELENGTH >= 490 && WAVELENGTH < 510 ) + RGB(1) = 0.0; + RGB(2) = 1.0; + RGB(3) = -(WAVELENGTH - 510) / (510 - 490); +elseif ( WAVELENGTH >= 510 && WAVELENGTH < 580 ) + RGB(1) = (WAVELENGTH - 510) / (580 - 510); + RGB(2) = 1.0; + RGB(3) = 0.0; +elseif ( WAVELENGTH >= 580 && WAVELENGTH < 645 ) + RGB(1) = 1.0; + RGB(2) = -(WAVELENGTH - 645) / (645 - 580); + RGB(3) = 0.0; +elseif ( WAVELENGTH >= 645 && WAVELENGTH < 781 ) + RGB(1) = 1.0; + RGB(2) = 0.0; + RGB(3) = 0.0; +else + RGB(1) = 0.0; + RGB(2) = 0.0; + RGB(3) = 0.0; +end + +% correct RGB +RGB = INTENSITY_MAX .* (RGB .* factor) .^GAMMA .* ( RGB > 0 ); + +return; + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <car...@us...> - 2012-03-13 18:08:51
|
Revision: 9864 http://octave.svn.sourceforge.net/octave/?rev=9864&view=rev Author: carandraug Date: 2012-03-13 18:08:40 +0000 (Tue, 13 Mar 2012) Log Message: ----------- mat2gray: big rewrite, function seems to not be working for several octave releases. Also should now be completely compatible with matlab Modified Paths: -------------- trunk/octave-forge/main/image/NEWS trunk/octave-forge/main/image/inst/mat2gray.m Modified: trunk/octave-forge/main/image/NEWS =================================================================== --- trunk/octave-forge/main/image/NEWS 2012-03-13 17:55:28 UTC (rev 9863) +++ trunk/octave-forge/main/image/NEWS 2012-03-13 18:08:40 UTC (rev 9864) @@ -46,6 +46,7 @@ isgray isrgb isind + mat2gray ** `isbw' now defines a black-and-white image as a binary non-sparse matrix. This is compatible with matlab. To use the old behaviour, Modified: trunk/octave-forge/main/image/inst/mat2gray.m =================================================================== --- trunk/octave-forge/main/image/inst/mat2gray.m 2012-03-13 17:55:28 UTC (rev 9863) +++ trunk/octave-forge/main/image/inst/mat2gray.m 2012-03-13 18:08:40 UTC (rev 9864) @@ -1,46 +1,75 @@ ## Copyright (C) 1999,2000 Kai Habel <kai...@gm...> -## Copyright (C) 2011 Carnë Draug <car...@gm...> +## Copyright (C) 2011, 2012 Carnë Draug <car...@gm...> ## -## This program 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. +## This program 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. ## -## This program 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. +## This program 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 this program; If not, see <http://www.gnu.org/licenses/>. +## You should have received a copy of the GNU General Public License along with +## this program; if not, see <http://www.gnu.org/licenses/>. ## -*- texinfo -*- -## @deftypefn {Function File} @var{I}= mat2gray (@var{M},[min max]) +## @deftypefn {Function File} {@var{I} =} mat2gray (@var{M}, [@var{min} @var{max}]) ## Converts a matrix to a intensity image. -## @seealso{gray2ind, ind2gray, rgb2gray} +## @seealso{gray2ind, ind2gray, rgb2gray, im2double, im2uin16, im2uint8, im2int16} ## @end deftypefn -function I = mat2gray (M, scale) +function out = mat2gray (in, scale) if (nargin < 1 || nargin > 2) print_usage; - elseif (!ismatrix (M)) - error ("mat2gray(M,...) M must be a matrix"); + elseif (!ismatrix (in) || ischar(in)) + error ("mat2gray: first argument must be a matrix"); elseif (nargin == 2 && (!isvector (scale) || numel (scale) != 2)) - error ("mat2gray(M,scale) scale must be a vector with 2 elements"); + error ("mat2gray: second argument must be a vector with 2 elements"); endif - ## what if the matrix has more than 2D? if (nargin == 1) - Mmin = min (min (M)); - Mmax = max (max (M)); - else - Mmin = min (scale (1), scale (2)); - Mmax = max (scale (1), scale (2)); + out_min = min (in(:)); + out_max = max (in(:)); + else + ## see more at the end for the cases where max and min are swapped + out_min = min (scale (1), scale (2)); + out_max = max (scale (1), scale (2)); endif - I = (M < Mmin) .* 0; - I = I + (M >= Mmin & M < Mmax) .* (1 / (Mmax - Mmin) * (M - Mmin)); - I = I + (M >= Mmax); + ## since max() and min() return a value of same class as input, + ## need to make this values double or the calculations later may fail + out_min = double (out_min); + out_max = double (out_max); + out = ones (size (in)); + if (out_min == out_max) + ## if max and min are the same, matlab seems to simple return 1s, even + ## for values under the minimum/maximum. As such, we are done here + return + endif + + out(in <= out_min) = 0; + ## no need to worry with values above or equal to out_max because + ## the output matrix was already generated with ones() + + ## it's faster to get the index of values between max and min only once + ## than to have it calculated on both sides of the assignment + idx = (in > out_min & in < out_max); + out(idx) = (1/(out_max - out_min)) * (double(in(idx)) - out_min); + + ## if the given min and max are in the inverse order... + if (nargin > 1 && scale(1) > scale (2)) + ## matlab seems to allow setting the min higher than the max but not by + ## checking which one is actually correct. Seems to just invert it + out = abs (out - 1); + endif + endfunction + +%!assert(mat2gray([1 2 3]), [0 0.5 1]); # standard use +%!assert(mat2gray(repmat ([1 2; 3 3], [1 1 3])), repmat ([0 0.5; 1 1], [1 1 3])); # setting min and max +%!assert(mat2gray([1 2 3], [2 2]), [1 1 1]); # equal min and max +%!assert(mat2gray([1 2 3], [3 1]), [1 0.5 0]); # max and min inverted This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |