From 2b550c2f63ebe553b61457488d0bb0bc0a324850 Mon Sep 17 00:00:00 2001 From: meshtag Date: Tue, 12 Jan 2021 17:33:01 +0530 Subject: [PATCH 01/10] Added all standard morphological transformations --- example/morphology.cpp | 175 +++++++++++++++++++++++++++++++++++++++++ example/original.png | Bin 0 -> 2082 bytes 2 files changed, 175 insertions(+) create mode 100644 example/morphology.cpp create mode 100644 example/original.png diff --git a/example/morphology.cpp b/example/morphology.cpp new file mode 100644 index 0000000000..27acd6d795 --- /dev/null +++ b/example/morphology.cpp @@ -0,0 +1,175 @@ +#include +#include +#include +#include +#include +#include + +boost::gil::gray8_image_t img; + +//This function is used for applying basic threshold and convolution operations which are applied +//under the hood for all morphological transformations. +template +boost::gil::gray8_image_t thresh_con_thresh(SrcView const& src_view, Kernel const& ker_mat,const int threshold1,const int threshold2) +{ + using namespace boost::gil; + boost::gil::gray8_image_t intermediate_img(src_view.dimensions()); + threshold_binary(src_view, view(intermediate_img),threshold1, 255); + detail::convolve_2d(view(intermediate_img), ker_mat, view(intermediate_img)); + threshold_binary(const_view(intermediate_img),view(intermediate_img),threshold2,255); + return intermediate_img; +} + +template +boost::gil::gray8_image_t dilate(SrcView const& src_view, Kernel const& ker_mat,const int iterations) +{ + boost::gil::gray8_image_t img_out_dilation(src_view.dimensions()); + img_out_dilation = img; + for(int i=0;i +boost::gil::gray8_image_t erode(SrcView const& src_view, Kernel const& ker_mat,const int iterations) +{ + boost::gil::gray8_image_t img_out_erosion(src_view.dimensions()); + img_out_erosion = img; + for(int i=0;i +boost::gil::gray8_image_t opening(SrcView const& src_view, Kernel const& ker_mat) +{ + boost::gil::gray8_image_t img_out_opening(src_view.dimensions()); + img_out_opening = erode(src_view,ker_mat,1); + return dilate(view(img_out_opening),ker_mat,1); +} + +template +boost::gil::gray8_image_t closing(SrcView const& src_view, Kernel const& ker_mat) +{ + boost::gil::gray8_image_t img_out_closing(src_view.dimensions()); + img_out_closing = dilate(src_view,ker_mat,1); + return erode(view(img_out_closing),ker_mat,1); +} + + +//This function calculates the difference between pixel values of first image_view and second +//image_view.This function can be used for rgb as well as grayscale images. +template +void difference_impl(SrcView const& src_view, DstView const& dst_view, DiffView const& diff_view) +{ + for (std::ptrdiff_t view_row = 0; view_row < src_view.height(); ++view_row) + for (std::ptrdiff_t view_col = 0; view_col < src_view.width(); ++view_col) + diff_view(view_col, view_row) = src_view(view_col,view_row) - dst_view(view_col,view_row); +} + + +template +void difference(SrcView const& src_view, DstView const& dst_view , DiffView const& diff_view) +{ + + BOOST_ASSERT(src_view.dimensions() == dst_view.dimensions()); + + for (std::size_t i = 0; i < src_view.num_channels(); i++) + { + difference_impl( + nth_channel_view(src_view, i), + nth_channel_view(dst_view, i), + nth_channel_view(diff_view, i) + ); + } +} + +template +boost::gil::gray8_image_t morphological_gradient(SrcView const& src_view, Kernel const& ker_mat) +{ + using namespace boost::gil; + gray8_image_t int_dilate(src_view.dimensions()),int_erode(src_view.dimensions()),res_image(src_view.dimensions()); + int_dilate = dilate(src_view,ker_mat,1); + int_erode = erode(src_view,ker_mat,1); + difference(view(int_dilate),view(int_erode),view(res_image)); + return res_image; +} + +template +boost::gil::gray8_image_t top_hat(SrcView const& src_view, Kernel const& ker_mat) +{ + using namespace boost::gil; + gray8_image_t int_opening(src_view.dimensions()),res_image(src_view.dimensions()); + int_opening = opening(src_view,ker_mat); + difference(src_view,view(int_opening),view(res_image)); + return res_image; +} + +template +boost::gil::gray8_image_t black_hat(SrcView const& src_view, Kernel const& ker_mat) +{ + using namespace boost::gil; + gray8_image_t int_closing(src_view.dimensions()),res_image(src_view.dimensions()); + int_closing = closing(src_view,ker_mat); + difference(view(int_closing), src_view,view(res_image)); + return res_image; +} + +//Summary of applied morphological concepts +//Structuring element is SE = [0.1,0.1,0.1] +// |0.1,0.1,0.1| +// [0.1,0.1,0.1] +//SE(1,1)(center pixel) is the one which coincides with the currently considered pixel of the +//image to be convolved. +//1.Dilation:If 1 or more bright pixels coincide with the structuring element during convolution, +//center pixel is made bright.We can vary the number of times dilation happens by varying the +//argument 'iterations' in the dilate function. +//2.Erosion:If 8 or more bright pixels coincide with the structuring element during convolution, +//center pixel is made bright.We can vary the number of times erosion happens by varying the +//argument 'iterations' in the erode function. +//3.Opening:Opening is just another name of erosion followed by dilation. +//It is useful in removing noise. +//4.Closing:Closing is reverse of Opening, Dilation followed by Erosion. +//It is useful in closing small holes inside the foreground objects, or small black points +//on the object. +//5.Morphological Gradient:It is the difference between dilation and erosion of an image. +//The result will look like the outline of the object. +//6.Top Hat:It is the difference between input image and Opening of the image. +//7.Black Hat:It is the difference between the closing of the input image and input image. + +//Functions have been made for applying above morphological transformations which +//return the transformed image. + +int main() +{ + using namespace boost::gil; + read_image("original.png", img, png_tag{}); + std::vectorker_vec(9,0.1f);//Structuring element + detail::kernel_2d ker_mat(ker_vec.begin(), ker_vec.size(), 1, 1); + gray8_image_t img_out_dilation(img.dimensions()),img_out_erosion(img.dimensions()),img_out_opening(img.dimensions()); + gray8_image_t img_out_closing(img.dimensions()),img_out_mg(img.dimensions()),img_out_top_hat(img.dimensions()); + gray8_image_t img_out_black_hat(img.dimensions()); + //dilate(input_image_view,structuring_element,iterations) + img_out_dilation = dilate(view(img),ker_mat,1); + //erode(input_image_view,structuring_element,iterations) + img_out_erosion = erode(view(img),ker_mat,1); + //opening(input_image_view,structuring_element) + img_out_opening = opening(view(img),ker_mat); + //closing(input_image_view,structuring_element) + img_out_closing = closing(view(img),ker_mat); + //morphological_gradient(input_image_view,structuring_element) + img_out_mg = morphological_gradient(view(img),ker_mat); + //top_hat(input_image_view,structuring_element) + img_out_top_hat = top_hat(view(img),ker_mat); + //black_hat(input_image_view,structuring_element) + img_out_black_hat = black_hat(view(img),ker_mat); + + //Saving results of above morphological transformations. + write_view("out-morphological-example-dilation.png", view(img_out_dilation), png_tag{}); + write_view("out-morphological-example-erosion.png", view(img_out_erosion), png_tag{}); + write_view("out-morphological-example-opening.png", view(img_out_opening), png_tag{}); + write_view("out-morphological-example-closing.png", view(img_out_closing), png_tag{}); + write_view("out-morphological-example-morphological_gradient.png", view(img_out_mg), png_tag{}); + write_view("out-morphological-example-top_hat.png", view(img_out_top_hat), png_tag{}); + write_view("out-morphological-example-black_hat.png", view(img_out_black_hat), png_tag{}); +} diff --git a/example/original.png b/example/original.png new file mode 100644 index 0000000000000000000000000000000000000000..b63e99ed9da7b769fd4fe45826f1f5118fb24297 GIT binary patch literal 2082 zcmZ8iZB!Fi8U~6e6lgL-Es3HqNe0s5Za%OUTm@l-02eGGm}5C53=p(+p&(Y24~YWK zK(s~zJ5gHBi8NB>s42CDEv14Z@)2P@Srsd~k^)M*T0KZn5ZybR-Tv4gbMJkhdGEdN zecmtn{lpkA521&Xlap7hir5V2d+@7Y0tY9@y4#~pPKzgFi49wdobPnWkNh0%QaSqS zjxOi@^TQ>-X)lhwvGd>?_lTT(es>3(tFzub(NvAy zIzL_N=%N<~u4pLwB>>1_qlr^ZWhdM<)3v6ru8s!PTca3@j-!I7^6GIpP-Cc@kD( zks#cOtGc|>&2*QNl z-@N~ND`WIcdN{QDW0^FG2q~KzompwR+{E4haX$RR>1DIiIl0YWB(C z_K7Nv)~o{Z13a*r3WW%+5Lo54{A?l}lG1*4jQtiQ8u_K%O}9bf&VeyPaBVBRWQ}Qs zRcaUYQyZ?^ztSFH-i`lH+1sWat0O6k$XzgUB>fM9Ywvt#c=&Nxe;Q zW`6;35cEMMAkh`){i+D%Gf-Lt5(%7#o<5a)H5d=XP>OUcwFe3z| z#s^FUXoj)3*|Mn+_*c{U+VTgCs-?@5=ZDgyW1TXt3HUFSpCtNS%?;aAHk~@2XY(~E zb?Rr~%I3JEtJ`P@dCAD=2_RC*sNSX!^z0zGmYLX2K*BgpbTszJ5|9vZQ2JO3I_5mA9KC5A zgw#;RNyoMLQ;NB zuIpv0R2`-J=4=?w6WDnJ^bvQWhrlk(&5n0-5K6yE)k7$R{kyFWDywzyWnvKDGT;jB zA{Uvnq2IQV|9mw4yu10A$t}u@1SflOIQ&177yja<=p+}nuK}^pB1sJhvjm(4G2q$w zsr3EYEf>OXddj@=v%^R~EF+qha?~~oB&pbDZN+efAm9dEFvC>>JXNI7Qp42(?1rdd zVx84*>I=1@ZT9A?m-CCaS~l(MdrGgS&xF5vazET1ruZ=TN?jkdn?AFDekOeXKVV0F u^w54g2gVt>+wmdSAYM%We=~M;&9AKA^Y#TxX!BmK`NwWdB+f=^4*UmVeU2^w literal 0 HcmV?d00001 From 48436fc82ab3d6ffbd2ce13d343640edc54ad02b Mon Sep 17 00:00:00 2001 From: meshtag Date: Thu, 14 Jan 2021 21:49:53 +0530 Subject: [PATCH 02/10] Improved comments and some other things --- example/morphology.cpp | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/example/morphology.cpp b/example/morphology.cpp index 27acd6d795..be27ee52d4 100644 --- a/example/morphology.cpp +++ b/example/morphology.cpp @@ -5,9 +5,8 @@ #include #include -boost::gil::gray8_image_t img; -//This function is used for applying basic threshold and convolution operations which are applied +//This function is used for applying basic thresholding and convolution operations which are applied //under the hood for all morphological transformations. template boost::gil::gray8_image_t thresh_con_thresh(SrcView const& src_view, Kernel const& ker_mat,const int threshold1,const int threshold2) @@ -20,26 +19,34 @@ boost::gil::gray8_image_t thresh_con_thresh(SrcView const& src_view, Kernel cons return intermediate_img; } +// Dilation:If 1 or more bright pixels coincide with the structuring element during convolution, +// center pixel is made bright.We can vary the number of times dilation happens by varying the +// argument 'iterations' in the dilate function. template boost::gil::gray8_image_t dilate(SrcView const& src_view, Kernel const& ker_mat,const int iterations) { boost::gil::gray8_image_t img_out_dilation(src_view.dimensions()); - img_out_dilation = img; + boost::gil::transform_pixels(src_view,view(img_out_dilation),[](const boost::gil::gray8_pixel_t& p){return p[0];}); for(int i=0;i boost::gil::gray8_image_t erode(SrcView const& src_view, Kernel const& ker_mat,const int iterations) { boost::gil::gray8_image_t img_out_erosion(src_view.dimensions()); - img_out_erosion = img; + boost::gil::transform_pixels(src_view,view(img_out_erosion),[](const boost::gil::gray8_pixel_t& p){return p[0];}); for(int i=0;i boost::gil::gray8_image_t opening(SrcView const& src_view, Kernel const& ker_mat) { @@ -48,6 +55,9 @@ boost::gil::gray8_image_t opening(SrcView const& src_view, Kernel const& ker_mat return dilate(view(img_out_opening),ker_mat,1); } +//Closing:Closing is reverse of Opening, Dilation followed by Erosion. +//It is useful in closing small holes inside the foreground objects, or small black points +//on the object. template boost::gil::gray8_image_t closing(SrcView const& src_view, Kernel const& ker_mat) { @@ -84,6 +94,8 @@ void difference(SrcView const& src_view, DstView const& dst_view , DiffView cons } } +//Morphological Gradient:It is the difference between dilation and erosion of an image. +//The result will look like the outline of the object. template boost::gil::gray8_image_t morphological_gradient(SrcView const& src_view, Kernel const& ker_mat) { @@ -95,6 +107,7 @@ boost::gil::gray8_image_t morphological_gradient(SrcView const& src_view, Kernel return res_image; } +//Top Hat:It is the difference between input image and Opening of the image. template boost::gil::gray8_image_t top_hat(SrcView const& src_view, Kernel const& ker_mat) { @@ -105,6 +118,7 @@ boost::gil::gray8_image_t top_hat(SrcView const& src_view, Kernel const& ker_mat return res_image; } +//Black Hat:It is the difference between the closing of the input image and input image. template boost::gil::gray8_image_t black_hat(SrcView const& src_view, Kernel const& ker_mat) { @@ -115,34 +129,16 @@ boost::gil::gray8_image_t black_hat(SrcView const& src_view, Kernel const& ker_m return res_image; } -//Summary of applied morphological concepts //Structuring element is SE = [0.1,0.1,0.1] // |0.1,0.1,0.1| // [0.1,0.1,0.1] //SE(1,1)(center pixel) is the one which coincides with the currently considered pixel of the //image to be convolved. -//1.Dilation:If 1 or more bright pixels coincide with the structuring element during convolution, -//center pixel is made bright.We can vary the number of times dilation happens by varying the -//argument 'iterations' in the dilate function. -//2.Erosion:If 8 or more bright pixels coincide with the structuring element during convolution, -//center pixel is made bright.We can vary the number of times erosion happens by varying the -//argument 'iterations' in the erode function. -//3.Opening:Opening is just another name of erosion followed by dilation. -//It is useful in removing noise. -//4.Closing:Closing is reverse of Opening, Dilation followed by Erosion. -//It is useful in closing small holes inside the foreground objects, or small black points -//on the object. -//5.Morphological Gradient:It is the difference between dilation and erosion of an image. -//The result will look like the outline of the object. -//6.Top Hat:It is the difference between input image and Opening of the image. -//7.Black Hat:It is the difference between the closing of the input image and input image. - -//Functions have been made for applying above morphological transformations which -//return the transformed image. int main() { using namespace boost::gil; + boost::gil::gray8_image_t img; read_image("original.png", img, png_tag{}); std::vectorker_vec(9,0.1f);//Structuring element detail::kernel_2d ker_mat(ker_vec.begin(), ker_vec.size(), 1, 1); From 14900be7116e0002090569a637d4d52928bc0cea Mon Sep 17 00:00:00 2001 From: meshtag Date: Sun, 17 Jan 2021 12:58:55 +0530 Subject: [PATCH 03/10] Applied adviced changes --- example/morphology.cpp | 135 +----------------- .../boost/gil/image_processing/morphology.hpp | 131 +++++++++++++++++ 2 files changed, 135 insertions(+), 131 deletions(-) create mode 100644 include/boost/gil/image_processing/morphology.hpp diff --git a/example/morphology.cpp b/example/morphology.cpp index be27ee52d4..15c4d158a9 100644 --- a/example/morphology.cpp +++ b/example/morphology.cpp @@ -1,137 +1,10 @@ -#include -#include #include +#include #include -#include -#include - -//This function is used for applying basic thresholding and convolution operations which are applied -//under the hood for all morphological transformations. -template -boost::gil::gray8_image_t thresh_con_thresh(SrcView const& src_view, Kernel const& ker_mat,const int threshold1,const int threshold2) -{ - using namespace boost::gil; - boost::gil::gray8_image_t intermediate_img(src_view.dimensions()); - threshold_binary(src_view, view(intermediate_img),threshold1, 255); - detail::convolve_2d(view(intermediate_img), ker_mat, view(intermediate_img)); - threshold_binary(const_view(intermediate_img),view(intermediate_img),threshold2,255); - return intermediate_img; -} - -// Dilation:If 1 or more bright pixels coincide with the structuring element during convolution, -// center pixel is made bright.We can vary the number of times dilation happens by varying the -// argument 'iterations' in the dilate function. -template -boost::gil::gray8_image_t dilate(SrcView const& src_view, Kernel const& ker_mat,const int iterations) -{ - boost::gil::gray8_image_t img_out_dilation(src_view.dimensions()); - boost::gil::transform_pixels(src_view,view(img_out_dilation),[](const boost::gil::gray8_pixel_t& p){return p[0];}); - for(int i=0;i -boost::gil::gray8_image_t erode(SrcView const& src_view, Kernel const& ker_mat,const int iterations) -{ - boost::gil::gray8_image_t img_out_erosion(src_view.dimensions()); - boost::gil::transform_pixels(src_view,view(img_out_erosion),[](const boost::gil::gray8_pixel_t& p){return p[0];}); - for(int i=0;i -boost::gil::gray8_image_t opening(SrcView const& src_view, Kernel const& ker_mat) -{ - boost::gil::gray8_image_t img_out_opening(src_view.dimensions()); - img_out_opening = erode(src_view,ker_mat,1); - return dilate(view(img_out_opening),ker_mat,1); -} - -//Closing:Closing is reverse of Opening, Dilation followed by Erosion. -//It is useful in closing small holes inside the foreground objects, or small black points -//on the object. -template -boost::gil::gray8_image_t closing(SrcView const& src_view, Kernel const& ker_mat) -{ - boost::gil::gray8_image_t img_out_closing(src_view.dimensions()); - img_out_closing = dilate(src_view,ker_mat,1); - return erode(view(img_out_closing),ker_mat,1); -} - - -//This function calculates the difference between pixel values of first image_view and second -//image_view.This function can be used for rgb as well as grayscale images. -template -void difference_impl(SrcView const& src_view, DstView const& dst_view, DiffView const& diff_view) -{ - for (std::ptrdiff_t view_row = 0; view_row < src_view.height(); ++view_row) - for (std::ptrdiff_t view_col = 0; view_col < src_view.width(); ++view_col) - diff_view(view_col, view_row) = src_view(view_col,view_row) - dst_view(view_col,view_row); -} - - -template -void difference(SrcView const& src_view, DstView const& dst_view , DiffView const& diff_view) -{ - - BOOST_ASSERT(src_view.dimensions() == dst_view.dimensions()); - - for (std::size_t i = 0; i < src_view.num_channels(); i++) - { - difference_impl( - nth_channel_view(src_view, i), - nth_channel_view(dst_view, i), - nth_channel_view(diff_view, i) - ); - } -} - -//Morphological Gradient:It is the difference between dilation and erosion of an image. -//The result will look like the outline of the object. -template -boost::gil::gray8_image_t morphological_gradient(SrcView const& src_view, Kernel const& ker_mat) -{ - using namespace boost::gil; - gray8_image_t int_dilate(src_view.dimensions()),int_erode(src_view.dimensions()),res_image(src_view.dimensions()); - int_dilate = dilate(src_view,ker_mat,1); - int_erode = erode(src_view,ker_mat,1); - difference(view(int_dilate),view(int_erode),view(res_image)); - return res_image; -} - -//Top Hat:It is the difference between input image and Opening of the image. -template -boost::gil::gray8_image_t top_hat(SrcView const& src_view, Kernel const& ker_mat) -{ - using namespace boost::gil; - gray8_image_t int_opening(src_view.dimensions()),res_image(src_view.dimensions()); - int_opening = opening(src_view,ker_mat); - difference(src_view,view(int_opening),view(res_image)); - return res_image; -} - -//Black Hat:It is the difference between the closing of the input image and input image. -template -boost::gil::gray8_image_t black_hat(SrcView const& src_view, Kernel const& ker_mat) -{ - using namespace boost::gil; - gray8_image_t int_closing(src_view.dimensions()),res_image(src_view.dimensions()); - int_closing = closing(src_view,ker_mat); - difference(view(int_closing), src_view,view(res_image)); - return res_image; -} - -//Structuring element is SE = [0.1,0.1,0.1] -// |0.1,0.1,0.1| -// [0.1,0.1,0.1] +//current structuring element is SE = [0.1,0.1,0.1] +// |0.1,0.1,0.1| +// [0.1,0.1,0.1] //SE(1,1)(center pixel) is the one which coincides with the currently considered pixel of the //image to be convolved. diff --git a/include/boost/gil/image_processing/morphology.hpp b/include/boost/gil/image_processing/morphology.hpp new file mode 100644 index 0000000000..ee29f9f8d0 --- /dev/null +++ b/include/boost/gil/image_processing/morphology.hpp @@ -0,0 +1,131 @@ +#ifndef BOOST_GIL_IMAGE_PROCESSING_MORPHOLOGY_HPP +#define BOOST_GIL_IMAGE_PROCESSING_MORPHOLOGY_HPP + +#include +#include +#include + + +//This function is used for applying basic thresholding and convolution operations which are applied +//under the hood for all morphological transformations. +template +boost::gil::gray8_image_t thresh_con_thresh(SrcView const& src_view, Kernel const& ker_mat,const int threshold1,const int threshold2) +{ + using namespace boost::gil; + boost::gil::gray8_image_t intermediate_img(src_view.dimensions()); + threshold_binary(src_view, view(intermediate_img),threshold1, 255); + detail::convolve_2d(view(intermediate_img), ker_mat, view(intermediate_img)); + threshold_binary(const_view(intermediate_img),view(intermediate_img),threshold2,255); + return intermediate_img; +} + +// Dilation:If 1 or more bright pixels coincide with the structuring element during convolution, +// center pixel is made bright.We can vary the number of times dilation happens by varying the +// argument 'iterations' in the dilate function. +template +boost::gil::gray8_image_t dilate(SrcView const& src_view, Kernel const& ker_mat,const int iterations) +{ + boost::gil::gray8_image_t img_out_dilation(src_view.dimensions()); + boost::gil::transform_pixels(src_view,view(img_out_dilation),[](const boost::gil::gray8_pixel_t& p){return p[0];}); + for(int i=0;i +boost::gil::gray8_image_t erode(SrcView const& src_view, Kernel const& ker_mat,const int iterations) +{ + boost::gil::gray8_image_t img_out_erosion(src_view.dimensions()); + boost::gil::transform_pixels(src_view,view(img_out_erosion),[](const boost::gil::gray8_pixel_t& p){return p[0];}); + for(int i=0;i +boost::gil::gray8_image_t opening(SrcView const& src_view, Kernel const& ker_mat) +{ + boost::gil::gray8_image_t img_out_opening(src_view.dimensions()); + img_out_opening = erode(src_view,ker_mat,1); + return dilate(view(img_out_opening),ker_mat,1); +} + +//Closing:Closing is reverse of Opening, Dilation followed by Erosion. +//It is useful in closing small holes inside the foreground objects, or small black points +//on the object. +template +boost::gil::gray8_image_t closing(SrcView const& src_view, Kernel const& ker_mat) +{ + boost::gil::gray8_image_t img_out_closing(src_view.dimensions()); + img_out_closing = dilate(src_view,ker_mat,1); + return erode(view(img_out_closing),ker_mat,1); +} + + +//This function calculates the difference between pixel values of first image_view and second +//image_view.This function can be used for rgb as well as grayscale images. +template +void difference_impl(SrcView const& src_view, DstView const& dst_view, DiffView const& diff_view) +{ + for (std::ptrdiff_t view_row = 0; view_row < src_view.height(); ++view_row) + for (std::ptrdiff_t view_col = 0; view_col < src_view.width(); ++view_col) + diff_view(view_col, view_row) = src_view(view_col,view_row) - dst_view(view_col,view_row); +} + + +template +void difference(SrcView const& src_view, DstView const& dst_view , DiffView const& diff_view) +{ + + BOOST_ASSERT(src_view.dimensions() == dst_view.dimensions()); + + for (std::size_t i = 0; i < src_view.num_channels(); i++) + { + difference_impl( + nth_channel_view(src_view, i), + nth_channel_view(dst_view, i), + nth_channel_view(diff_view, i) + ); + } +} + +//Morphological Gradient:It is the difference between dilation and erosion of an image. +//The result will look like the outline of the object. +template +boost::gil::gray8_image_t morphological_gradient(SrcView const& src_view, Kernel const& ker_mat) +{ + using namespace boost::gil; + gray8_image_t int_dilate(src_view.dimensions()),int_erode(src_view.dimensions()),res_image(src_view.dimensions()); + int_dilate = dilate(src_view,ker_mat,1); + int_erode = erode(src_view,ker_mat,1); + difference(view(int_dilate),view(int_erode),view(res_image)); + return res_image; +} + +//Top Hat:It is the difference between input image and Opening of the image. +template +boost::gil::gray8_image_t top_hat(SrcView const& src_view, Kernel const& ker_mat) +{ + using namespace boost::gil; + gray8_image_t int_opening(src_view.dimensions()),res_image(src_view.dimensions()); + int_opening = opening(src_view,ker_mat); + difference(src_view,view(int_opening),view(res_image)); + return res_image; +} + +//Black Hat:It is the difference between the closing of the input image and input image. +template +boost::gil::gray8_image_t black_hat(SrcView const& src_view, Kernel const& ker_mat) +{ + using namespace boost::gil; + gray8_image_t int_closing(src_view.dimensions()),res_image(src_view.dimensions()); + int_closing = closing(src_view,ker_mat); + difference(view(int_closing), src_view,view(res_image)); + return res_image; +} +#endif //BOOST_GIL_IMAGE_PROCESSING_MORPHOLOGY_HPP \ No newline at end of file From 53d92b28451757a05a5043cdac1e9e96b13b3740 Mon Sep 17 00:00:00 2001 From: meshtag Date: Sun, 17 Jan 2021 13:00:00 +0530 Subject: [PATCH 04/10] Applied adviced changes --- example/morphology.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/morphology.cpp b/example/morphology.cpp index 15c4d158a9..304e409147 100644 --- a/example/morphology.cpp +++ b/example/morphology.cpp @@ -6,7 +6,7 @@ // |0.1,0.1,0.1| // [0.1,0.1,0.1] //SE(1,1)(center pixel) is the one which coincides with the currently considered pixel of the -//image to be convolved. +//image to be convolved. The structuring element can be easily changed by the user. int main() { From 6ac3102cec60370f6e7ce590bacf0d1a591f3010 Mon Sep 17 00:00:00 2001 From: meshtag Date: Wed, 20 Jan 2021 17:05:51 +0530 Subject: [PATCH 05/10] Should handle grayscale dilation/erosion --- example/morphology.cpp | 14 ++-- .../boost/gil/image_processing/morphology.hpp | 70 +++++++++++++++---- 2 files changed, 66 insertions(+), 18 deletions(-) diff --git a/example/morphology.cpp b/example/morphology.cpp index 304e409147..dcd0a17030 100644 --- a/example/morphology.cpp +++ b/example/morphology.cpp @@ -2,9 +2,9 @@ #include #include -//current structuring element is SE = [0.1,0.1,0.1] -// |0.1,0.1,0.1| -// [0.1,0.1,0.1] +//Default structuring element is SE = [1,1,1] +// |1,1,1| +// [1,1,1] //SE(1,1)(center pixel) is the one which coincides with the currently considered pixel of the //image to be convolved. The structuring element can be easily changed by the user. @@ -13,7 +13,13 @@ int main() using namespace boost::gil; boost::gil::gray8_image_t img; read_image("original.png", img, png_tag{}); - std::vectorker_vec(9,0.1f);//Structuring element + + //Image can be converted to a binary format with high value as 255 and low value as 0 + //by uncommenting the following threshold operator.This can be used for binary morphological + //operations. + threshold_binary(view(img), view(img),170, 255); + + std::vectorker_vec(9,1.0f);//Structuring element detail::kernel_2d ker_mat(ker_vec.begin(), ker_vec.size(), 1, 1); gray8_image_t img_out_dilation(img.dimensions()),img_out_erosion(img.dimensions()),img_out_opening(img.dimensions()); gray8_image_t img_out_closing(img.dimensions()),img_out_mg(img.dimensions()),img_out_top_hat(img.dimensions()); diff --git a/include/boost/gil/image_processing/morphology.hpp b/include/boost/gil/image_processing/morphology.hpp index ee29f9f8d0..2bd1c20c2e 100644 --- a/include/boost/gil/image_processing/morphology.hpp +++ b/include/boost/gil/image_processing/morphology.hpp @@ -1,26 +1,68 @@ #ifndef BOOST_GIL_IMAGE_PROCESSING_MORPHOLOGY_HPP #define BOOST_GIL_IMAGE_PROCESSING_MORPHOLOGY_HPP -#include #include -#include +template +void morph_impl(SrcView const& src_view, DstView const& dst_view, Kernel const& kernel,const int identifier) +{ + int flip_ker_row, flip_ker_col, row_boundary, col_boundary; + int max_overlapped_element,min_overlapped_element; + for (std::ptrdiff_t view_row = 0; view_row < src_view.height(); ++view_row) + { + for (std::ptrdiff_t view_col = 0; view_col < src_view.width(); ++view_col) + { + max_overlapped_element = 0,min_overlapped_element = 256; + for (std::size_t kernel_row = 0; kernel_row < kernel.size(); ++kernel_row) + { + flip_ker_row = kernel.size() - 1 - kernel_row; // row index of flipped kernel + + for (std::size_t kernel_col = 0; kernel_col < kernel.size(); ++kernel_col) + { + flip_ker_col = kernel.size() - 1 - kernel_col; // column index of flipped kernel + + // index of input signal, used for checking boundary + row_boundary = view_row + (kernel.center_y() - flip_ker_row); + col_boundary = view_col + (kernel.center_x() - flip_ker_col); + + // ignore input samples which are out of bound + if (row_boundary >= 0 && row_boundary < src_view.height() && + col_boundary >= 0 && col_boundary < src_view.width()) + { + if(src_view(col_boundary, row_boundary) > max_overlapped_element) + max_overlapped_element = src_view(col_boundary, row_boundary); + if(src_view(col_boundary, row_boundary) < min_overlapped_element) + min_overlapped_element = src_view(col_boundary, row_boundary); + } + } + } + if(identifier)//identifier = 1 for dilation + dst_view(view_col, view_row) = max_overlapped_element; + else //identifier = 0 for erosion + dst_view(view_col, view_row) = min_overlapped_element; + } + } +} -//This function is used for applying basic thresholding and convolution operations which are applied -//under the hood for all morphological transformations. template -boost::gil::gray8_image_t thresh_con_thresh(SrcView const& src_view, Kernel const& ker_mat,const int threshold1,const int threshold2) +boost::gil::gray8_image_t morph(SrcView const& src_view, Kernel const& ker_mat,const int identifier) { using namespace boost::gil; + BOOST_ASSERT(ker_mat.size() != 0); boost::gil::gray8_image_t intermediate_img(src_view.dimensions()); - threshold_binary(src_view, view(intermediate_img),threshold1, 255); - detail::convolve_2d(view(intermediate_img), ker_mat, view(intermediate_img)); - threshold_binary(const_view(intermediate_img),view(intermediate_img),threshold2,255); + for (std::size_t i = 0; i < src_view.num_channels(); i++) + { + morph_impl( + nth_channel_view(src_view, i), + nth_channel_view(view(intermediate_img), i), + ker_mat,identifier + ); + } return intermediate_img; } -// Dilation:If 1 or more bright pixels coincide with the structuring element during convolution, -// center pixel is made bright.We can vary the number of times dilation happens by varying the +// Dilation:Give the maximum overlapped value to the pixel overlapping with the center element of +//structuring element.We can vary the number of times dilation happens by varying the // argument 'iterations' in the dilate function. template boost::gil::gray8_image_t dilate(SrcView const& src_view, Kernel const& ker_mat,const int iterations) @@ -28,12 +70,12 @@ boost::gil::gray8_image_t dilate(SrcView const& src_view, Kernel const& ker_mat, boost::gil::gray8_image_t img_out_dilation(src_view.dimensions()); boost::gil::transform_pixels(src_view,view(img_out_dilation),[](const boost::gil::gray8_pixel_t& p){return p[0];}); for(int i=0;i boost::gil::gray8_image_t erode(SrcView const& src_view, Kernel const& ker_mat,const int iterations) @@ -41,7 +83,7 @@ boost::gil::gray8_image_t erode(SrcView const& src_view, Kernel const& ker_mat,c boost::gil::gray8_image_t img_out_erosion(src_view.dimensions()); boost::gil::transform_pixels(src_view,view(img_out_erosion),[](const boost::gil::gray8_pixel_t& p){return p[0];}); for(int i=0;i Date: Fri, 22 Jan 2021 00:58:18 +0530 Subject: [PATCH 06/10] Checking --- example/morphology.cpp | 50 ----- example/original.png | Bin 2082 -> 0 bytes .../boost/gil/image_processing/morphology.hpp | 173 ------------------ 3 files changed, 223 deletions(-) delete mode 100644 example/morphology.cpp delete mode 100644 example/original.png delete mode 100644 include/boost/gil/image_processing/morphology.hpp diff --git a/example/morphology.cpp b/example/morphology.cpp deleted file mode 100644 index dcd0a17030..0000000000 --- a/example/morphology.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include -#include - -//Default structuring element is SE = [1,1,1] -// |1,1,1| -// [1,1,1] -//SE(1,1)(center pixel) is the one which coincides with the currently considered pixel of the -//image to be convolved. The structuring element can be easily changed by the user. - -int main() -{ - using namespace boost::gil; - boost::gil::gray8_image_t img; - read_image("original.png", img, png_tag{}); - - //Image can be converted to a binary format with high value as 255 and low value as 0 - //by uncommenting the following threshold operator.This can be used for binary morphological - //operations. - threshold_binary(view(img), view(img),170, 255); - - std::vectorker_vec(9,1.0f);//Structuring element - detail::kernel_2d ker_mat(ker_vec.begin(), ker_vec.size(), 1, 1); - gray8_image_t img_out_dilation(img.dimensions()),img_out_erosion(img.dimensions()),img_out_opening(img.dimensions()); - gray8_image_t img_out_closing(img.dimensions()),img_out_mg(img.dimensions()),img_out_top_hat(img.dimensions()); - gray8_image_t img_out_black_hat(img.dimensions()); - //dilate(input_image_view,structuring_element,iterations) - img_out_dilation = dilate(view(img),ker_mat,1); - //erode(input_image_view,structuring_element,iterations) - img_out_erosion = erode(view(img),ker_mat,1); - //opening(input_image_view,structuring_element) - img_out_opening = opening(view(img),ker_mat); - //closing(input_image_view,structuring_element) - img_out_closing = closing(view(img),ker_mat); - //morphological_gradient(input_image_view,structuring_element) - img_out_mg = morphological_gradient(view(img),ker_mat); - //top_hat(input_image_view,structuring_element) - img_out_top_hat = top_hat(view(img),ker_mat); - //black_hat(input_image_view,structuring_element) - img_out_black_hat = black_hat(view(img),ker_mat); - - //Saving results of above morphological transformations. - write_view("out-morphological-example-dilation.png", view(img_out_dilation), png_tag{}); - write_view("out-morphological-example-erosion.png", view(img_out_erosion), png_tag{}); - write_view("out-morphological-example-opening.png", view(img_out_opening), png_tag{}); - write_view("out-morphological-example-closing.png", view(img_out_closing), png_tag{}); - write_view("out-morphological-example-morphological_gradient.png", view(img_out_mg), png_tag{}); - write_view("out-morphological-example-top_hat.png", view(img_out_top_hat), png_tag{}); - write_view("out-morphological-example-black_hat.png", view(img_out_black_hat), png_tag{}); -} diff --git a/example/original.png b/example/original.png deleted file mode 100644 index b63e99ed9da7b769fd4fe45826f1f5118fb24297..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2082 zcmZ8iZB!Fi8U~6e6lgL-Es3HqNe0s5Za%OUTm@l-02eGGm}5C53=p(+p&(Y24~YWK zK(s~zJ5gHBi8NB>s42CDEv14Z@)2P@Srsd~k^)M*T0KZn5ZybR-Tv4gbMJkhdGEdN zecmtn{lpkA521&Xlap7hir5V2d+@7Y0tY9@y4#~pPKzgFi49wdobPnWkNh0%QaSqS zjxOi@^TQ>-X)lhwvGd>?_lTT(es>3(tFzub(NvAy zIzL_N=%N<~u4pLwB>>1_qlr^ZWhdM<)3v6ru8s!PTca3@j-!I7^6GIpP-Cc@kD( zks#cOtGc|>&2*QNl z-@N~ND`WIcdN{QDW0^FG2q~KzompwR+{E4haX$RR>1DIiIl0YWB(C z_K7Nv)~o{Z13a*r3WW%+5Lo54{A?l}lG1*4jQtiQ8u_K%O}9bf&VeyPaBVBRWQ}Qs zRcaUYQyZ?^ztSFH-i`lH+1sWat0O6k$XzgUB>fM9Ywvt#c=&Nxe;Q zW`6;35cEMMAkh`){i+D%Gf-Lt5(%7#o<5a)H5d=XP>OUcwFe3z| z#s^FUXoj)3*|Mn+_*c{U+VTgCs-?@5=ZDgyW1TXt3HUFSpCtNS%?;aAHk~@2XY(~E zb?Rr~%I3JEtJ`P@dCAD=2_RC*sNSX!^z0zGmYLX2K*BgpbTszJ5|9vZQ2JO3I_5mA9KC5A zgw#;RNyoMLQ;NB zuIpv0R2`-J=4=?w6WDnJ^bvQWhrlk(&5n0-5K6yE)k7$R{kyFWDywzyWnvKDGT;jB zA{Uvnq2IQV|9mw4yu10A$t}u@1SflOIQ&177yja<=p+}nuK}^pB1sJhvjm(4G2q$w zsr3EYEf>OXddj@=v%^R~EF+qha?~~oB&pbDZN+efAm9dEFvC>>JXNI7Qp42(?1rdd zVx84*>I=1@ZT9A?m-CCaS~l(MdrGgS&xF5vazET1ruZ=TN?jkdn?AFDekOeXKVV0F u^w54g2gVt>+wmdSAYM%We=~M;&9AKA^Y#TxX!BmK`NwWdB+f=^4*UmVeU2^w diff --git a/include/boost/gil/image_processing/morphology.hpp b/include/boost/gil/image_processing/morphology.hpp deleted file mode 100644 index 2bd1c20c2e..0000000000 --- a/include/boost/gil/image_processing/morphology.hpp +++ /dev/null @@ -1,173 +0,0 @@ -#ifndef BOOST_GIL_IMAGE_PROCESSING_MORPHOLOGY_HPP -#define BOOST_GIL_IMAGE_PROCESSING_MORPHOLOGY_HPP - -#include - -template -void morph_impl(SrcView const& src_view, DstView const& dst_view, Kernel const& kernel,const int identifier) -{ - int flip_ker_row, flip_ker_col, row_boundary, col_boundary; - int max_overlapped_element,min_overlapped_element; - for (std::ptrdiff_t view_row = 0; view_row < src_view.height(); ++view_row) - { - for (std::ptrdiff_t view_col = 0; view_col < src_view.width(); ++view_col) - { - max_overlapped_element = 0,min_overlapped_element = 256; - for (std::size_t kernel_row = 0; kernel_row < kernel.size(); ++kernel_row) - { - flip_ker_row = kernel.size() - 1 - kernel_row; // row index of flipped kernel - - for (std::size_t kernel_col = 0; kernel_col < kernel.size(); ++kernel_col) - { - flip_ker_col = kernel.size() - 1 - kernel_col; // column index of flipped kernel - - // index of input signal, used for checking boundary - row_boundary = view_row + (kernel.center_y() - flip_ker_row); - col_boundary = view_col + (kernel.center_x() - flip_ker_col); - - // ignore input samples which are out of bound - if (row_boundary >= 0 && row_boundary < src_view.height() && - col_boundary >= 0 && col_boundary < src_view.width()) - { - if(src_view(col_boundary, row_boundary) > max_overlapped_element) - max_overlapped_element = src_view(col_boundary, row_boundary); - if(src_view(col_boundary, row_boundary) < min_overlapped_element) - min_overlapped_element = src_view(col_boundary, row_boundary); - } - } - } - if(identifier)//identifier = 1 for dilation - dst_view(view_col, view_row) = max_overlapped_element; - else //identifier = 0 for erosion - dst_view(view_col, view_row) = min_overlapped_element; - } - } -} - -template -boost::gil::gray8_image_t morph(SrcView const& src_view, Kernel const& ker_mat,const int identifier) -{ - using namespace boost::gil; - BOOST_ASSERT(ker_mat.size() != 0); - boost::gil::gray8_image_t intermediate_img(src_view.dimensions()); - for (std::size_t i = 0; i < src_view.num_channels(); i++) - { - morph_impl( - nth_channel_view(src_view, i), - nth_channel_view(view(intermediate_img), i), - ker_mat,identifier - ); - } - return intermediate_img; -} - -// Dilation:Give the maximum overlapped value to the pixel overlapping with the center element of -//structuring element.We can vary the number of times dilation happens by varying the -// argument 'iterations' in the dilate function. -template -boost::gil::gray8_image_t dilate(SrcView const& src_view, Kernel const& ker_mat,const int iterations) -{ - boost::gil::gray8_image_t img_out_dilation(src_view.dimensions()); - boost::gil::transform_pixels(src_view,view(img_out_dilation),[](const boost::gil::gray8_pixel_t& p){return p[0];}); - for(int i=0;i -boost::gil::gray8_image_t erode(SrcView const& src_view, Kernel const& ker_mat,const int iterations) -{ - boost::gil::gray8_image_t img_out_erosion(src_view.dimensions()); - boost::gil::transform_pixels(src_view,view(img_out_erosion),[](const boost::gil::gray8_pixel_t& p){return p[0];}); - for(int i=0;i -boost::gil::gray8_image_t opening(SrcView const& src_view, Kernel const& ker_mat) -{ - boost::gil::gray8_image_t img_out_opening(src_view.dimensions()); - img_out_opening = erode(src_view,ker_mat,1); - return dilate(view(img_out_opening),ker_mat,1); -} - -//Closing:Closing is reverse of Opening, Dilation followed by Erosion. -//It is useful in closing small holes inside the foreground objects, or small black points -//on the object. -template -boost::gil::gray8_image_t closing(SrcView const& src_view, Kernel const& ker_mat) -{ - boost::gil::gray8_image_t img_out_closing(src_view.dimensions()); - img_out_closing = dilate(src_view,ker_mat,1); - return erode(view(img_out_closing),ker_mat,1); -} - - -//This function calculates the difference between pixel values of first image_view and second -//image_view.This function can be used for rgb as well as grayscale images. -template -void difference_impl(SrcView const& src_view, DstView const& dst_view, DiffView const& diff_view) -{ - for (std::ptrdiff_t view_row = 0; view_row < src_view.height(); ++view_row) - for (std::ptrdiff_t view_col = 0; view_col < src_view.width(); ++view_col) - diff_view(view_col, view_row) = src_view(view_col,view_row) - dst_view(view_col,view_row); -} - - -template -void difference(SrcView const& src_view, DstView const& dst_view , DiffView const& diff_view) -{ - - BOOST_ASSERT(src_view.dimensions() == dst_view.dimensions()); - - for (std::size_t i = 0; i < src_view.num_channels(); i++) - { - difference_impl( - nth_channel_view(src_view, i), - nth_channel_view(dst_view, i), - nth_channel_view(diff_view, i) - ); - } -} - -//Morphological Gradient:It is the difference between dilation and erosion of an image. -//The result will look like the outline of the object. -template -boost::gil::gray8_image_t morphological_gradient(SrcView const& src_view, Kernel const& ker_mat) -{ - using namespace boost::gil; - gray8_image_t int_dilate(src_view.dimensions()),int_erode(src_view.dimensions()),res_image(src_view.dimensions()); - int_dilate = dilate(src_view,ker_mat,1); - int_erode = erode(src_view,ker_mat,1); - difference(view(int_dilate),view(int_erode),view(res_image)); - return res_image; -} - -//Top Hat:It is the difference between input image and Opening of the image. -template -boost::gil::gray8_image_t top_hat(SrcView const& src_view, Kernel const& ker_mat) -{ - using namespace boost::gil; - gray8_image_t int_opening(src_view.dimensions()),res_image(src_view.dimensions()); - int_opening = opening(src_view,ker_mat); - difference(src_view,view(int_opening),view(res_image)); - return res_image; -} - -//Black Hat:It is the difference between the closing of the input image and input image. -template -boost::gil::gray8_image_t black_hat(SrcView const& src_view, Kernel const& ker_mat) -{ - using namespace boost::gil; - gray8_image_t int_closing(src_view.dimensions()),res_image(src_view.dimensions()); - int_closing = closing(src_view,ker_mat); - difference(view(int_closing), src_view,view(res_image)); - return res_image; -} -#endif //BOOST_GIL_IMAGE_PROCESSING_MORPHOLOGY_HPP \ No newline at end of file From 093510abb42bb7f7fb3f10ea5069720e18b54dba Mon Sep 17 00:00:00 2001 From: meshtag Date: Fri, 12 Mar 2021 21:14:22 +0530 Subject: [PATCH 07/10] Port TuttleOFX shrink extension Add shrink First checkpoint test cases added Add pattern Updates Updates Port TuttleOFX extensions Improve comments Update copyright Improve copyright header Pass build Add aligned extendion Remove headers Add shrink --- .../gil/extension/toolbox/metafunctions.hpp | 1 + .../toolbox/metafunctions/shrink.hpp | 49 +++++++++++++++++++ test/extension/toolbox/CMakeLists.txt | 3 +- test/extension/toolbox/Jamfile | 1 + test/extension/toolbox/shrink.cpp | 31 ++++++++++++ 5 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 include/boost/gil/extension/toolbox/metafunctions/shrink.hpp create mode 100644 test/extension/toolbox/shrink.cpp diff --git a/include/boost/gil/extension/toolbox/metafunctions.hpp b/include/boost/gil/extension/toolbox/metafunctions.hpp index 16d7ee0184..b76491161c 100644 --- a/include/boost/gil/extension/toolbox/metafunctions.hpp +++ b/include/boost/gil/extension/toolbox/metafunctions.hpp @@ -16,5 +16,6 @@ #include #include #include +#include #endif diff --git a/include/boost/gil/extension/toolbox/metafunctions/shrink.hpp b/include/boost/gil/extension/toolbox/metafunctions/shrink.hpp new file mode 100644 index 0000000000..1c1be43199 --- /dev/null +++ b/include/boost/gil/extension/toolbox/metafunctions/shrink.hpp @@ -0,0 +1,49 @@ +// Copyright Tom Brinkman 2008. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef _shrink_hpp_ +#define _shrink_hpp_ + +#include + +namespace boost { namespace gil { + +/// \brief Assigns a smaller subimage view of the view given as first parameter to the +/// destination/resultant view given as second parameter to the overloaded '()' operator. +/// The dimensions of the smaller view are specified by struct constructor parameters. +template +struct shrink +{ + double left; + double top; + double right; + double bottom; + + shrink(double left = 5, double top = 5, double right = 5, double bottom = 5) + : left(left) + , top(top) + , right(right) + , bottom(bottom) + { + } + + void operator()(view_t& view, view_t& dstView) + { + if(left < 1.0) + left *= view.width(); + if(right < 1.0) + right *= view.width(); + if(top < 1.0) + top *= view.height(); + if(bottom < 1.0) + bottom *= view.height(); + + double width = view.width() - left - right; + double height = view.height() - top - bottom; + dstView = boost::gil::subimage_view(view, (int)left, (int)top, (int)width, (int)height); + } +}; +} } + +#endif diff --git a/test/extension/toolbox/CMakeLists.txt b/test/extension/toolbox/CMakeLists.txt index 70df68db42..f816b4c3fc 100644 --- a/test/extension/toolbox/CMakeLists.txt +++ b/test/extension/toolbox/CMakeLists.txt @@ -24,7 +24,8 @@ foreach(_name is_bit_aligned is_homogeneous pixel_bit_size - subchroma_image) + subchroma_image + shrink) set(_test t_ext_toolbox_${_name}) set(_target test_ext_toolbox_${_name}) diff --git a/test/extension/toolbox/Jamfile b/test/extension/toolbox/Jamfile index a2a78f7bed..3cbc5c57c6 100644 --- a/test/extension/toolbox/Jamfile +++ b/test/extension/toolbox/Jamfile @@ -27,6 +27,7 @@ run color_convert_lab.cpp ; run color_convert_luminance.cpp ; run color_convert_xyz.cpp ; run indexed_image.cpp ; +run shrink.cpp ; # TODO: Add subchroma_image.cpp after fixing run-time failure, # for details see https://github.com/boostorg/gil/pull/164 diff --git a/test/extension/toolbox/shrink.cpp b/test/extension/toolbox/shrink.cpp new file mode 100644 index 0000000000..6a155692f6 --- /dev/null +++ b/test/extension/toolbox/shrink.cpp @@ -0,0 +1,31 @@ +// +// Copyright 2021 Prathamesh Tagore +// +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +// Reference for test case was taken from +// https://github.com/tuttleofx/TuttleOFX/blob/develop/libraries/boostHack/boost/gil/extension/toolbox/shrink.tests.cpp + +#include +#include + +namespace gil = boost::gil; + +int main() +{ + gil::rgb8_image_t original_img(20, 20), expected_img(12, 8); + gil::rgb8_view_t original_img_view = gil::view(original_img), obtained_img_view; + + gil::fill_pixels(original_img_view, gil::rgb8_pixel_t(255, 255, 255)); + gil::fill_pixels(gil::view(expected_img), gil::rgb8_pixel_t(255, 255, 255)); + + gil::shrink shrink(0.20, 0.30, 0.20, 0.30); + shrink(original_img_view, obtained_img_view); + + BOOST_TEST(gil::equal_pixels(obtained_img_view, gil::view(expected_img))); + + return boost::report_errors(); +} \ No newline at end of file From b115fe91a0a64df725aa7e6cbbdce3658c96f2b4 Mon Sep 17 00:00:00 2001 From: meshtag Date: Thu, 18 Mar 2021 12:32:46 +0530 Subject: [PATCH 08/10] Replace C style casting with static_cast --- include/boost/gil/extension/toolbox/metafunctions/shrink.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/gil/extension/toolbox/metafunctions/shrink.hpp b/include/boost/gil/extension/toolbox/metafunctions/shrink.hpp index 1c1be43199..ede177a92a 100644 --- a/include/boost/gil/extension/toolbox/metafunctions/shrink.hpp +++ b/include/boost/gil/extension/toolbox/metafunctions/shrink.hpp @@ -41,7 +41,9 @@ struct shrink double width = view.width() - left - right; double height = view.height() - top - bottom; - dstView = boost::gil::subimage_view(view, (int)left, (int)top, (int)width, (int)height); + dstView = boost::gil::subimage_view(view, static_cast(left), + static_cast(top), static_cast(width), + static_cast(height)); } }; } } From a2ab525532fb9ffe2aade9c367abcccaf2f40086 Mon Sep 17 00:00:00 2001 From: meshtag Date: Wed, 24 Mar 2021 15:04:44 +0530 Subject: [PATCH 09/10] Improve formatting Improve formatting --- .../extension/toolbox/metafunctions/shrink.hpp | 18 +++++++++--------- test/extension/toolbox/shrink.cpp | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/boost/gil/extension/toolbox/metafunctions/shrink.hpp b/include/boost/gil/extension/toolbox/metafunctions/shrink.hpp index ede177a92a..bd9b14650d 100644 --- a/include/boost/gil/extension/toolbox/metafunctions/shrink.hpp +++ b/include/boost/gil/extension/toolbox/metafunctions/shrink.hpp @@ -7,7 +7,7 @@ #include -namespace boost { namespace gil { +namespace boost { namespace gil { /// \brief Assigns a smaller subimage view of the view given as first parameter to the /// destination/resultant view given as second parameter to the overloaded '()' operator. @@ -30,22 +30,22 @@ struct shrink void operator()(view_t& view, view_t& dstView) { - if(left < 1.0) + if (left < 1.0) left *= view.width(); - if(right < 1.0) + if (right < 1.0) right *= view.width(); - if(top < 1.0) + if (top < 1.0) top *= view.height(); - if(bottom < 1.0) + if (bottom < 1.0) bottom *= view.height(); double width = view.width() - left - right; double height = view.height() - top - bottom; dstView = boost::gil::subimage_view(view, static_cast(left), - static_cast(top), static_cast(width), - static_cast(height)); + static_cast(top), static_cast(width), + static_cast(height)); } -}; -} } +}; // shrink +}} // namespace boost::gil #endif diff --git a/test/extension/toolbox/shrink.cpp b/test/extension/toolbox/shrink.cpp index 6a155692f6..b081e22f00 100644 --- a/test/extension/toolbox/shrink.cpp +++ b/test/extension/toolbox/shrink.cpp @@ -28,4 +28,4 @@ int main() BOOST_TEST(gil::equal_pixels(obtained_img_view, gil::view(expected_img))); return boost::report_errors(); -} \ No newline at end of file +} From 06ea1ff7fa7d001ecace0631ef67c46ecaa27980 Mon Sep 17 00:00:00 2001 From: meshtag Date: Sat, 10 Apr 2021 09:46:39 +0530 Subject: [PATCH 10/10] Modified as per first review and compiler warnings suppression --- .../toolbox/metafunctions/shrink.hpp | 35 ++++++++++--------- test/extension/toolbox/CMakeLists.txt | 4 +-- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/include/boost/gil/extension/toolbox/metafunctions/shrink.hpp b/include/boost/gil/extension/toolbox/metafunctions/shrink.hpp index bd9b14650d..21a18b57e7 100644 --- a/include/boost/gil/extension/toolbox/metafunctions/shrink.hpp +++ b/include/boost/gil/extension/toolbox/metafunctions/shrink.hpp @@ -2,8 +2,8 @@ // Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#ifndef _shrink_hpp_ -#define _shrink_hpp_ +#ifndef BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_SHRINK_HPP +#define BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_SHRINK_HPP #include @@ -12,7 +12,7 @@ namespace boost { namespace gil { /// \brief Assigns a smaller subimage view of the view given as first parameter to the /// destination/resultant view given as second parameter to the overloaded '()' operator. /// The dimensions of the smaller view are specified by struct constructor parameters. -template +template struct shrink { double left; @@ -20,27 +20,30 @@ struct shrink double right; double bottom; - shrink(double left = 5, double top = 5, double right = 5, double bottom = 5) - : left(left) - , top(top) - , right(right) - , bottom(bottom) + shrink(double left_param = 5, double top_param = 5, double right_param = 5, + double bottom_param = 5) + : left(left_param) + , top(top_param) + , right(right_param) + , bottom(bottom_param) { } - - void operator()(view_t& view, view_t& dstView) + + void operator()(View& view, View& dstView) { + double const view_width = static_cast(view.width()); + double const view_height = static_cast(view.height()); if (left < 1.0) - left *= view.width(); + left *= view_width; if (right < 1.0) - right *= view.width(); + right *= view_width; if (top < 1.0) - top *= view.height(); + top *= view_height; if (bottom < 1.0) - bottom *= view.height(); + bottom *= view_height; - double width = view.width() - left - right; - double height = view.height() - top - bottom; + double const width = view_width - left - right; + double const height = view_height - top - bottom; dstView = boost::gil::subimage_view(view, static_cast(left), static_cast(top), static_cast(width), static_cast(height)); diff --git a/test/extension/toolbox/CMakeLists.txt b/test/extension/toolbox/CMakeLists.txt index f816b4c3fc..d0d2e86181 100644 --- a/test/extension/toolbox/CMakeLists.txt +++ b/test/extension/toolbox/CMakeLists.txt @@ -24,8 +24,8 @@ foreach(_name is_bit_aligned is_homogeneous pixel_bit_size - subchroma_image - shrink) + shrink + subchroma_image) set(_test t_ext_toolbox_${_name}) set(_target test_ext_toolbox_${_name})