Morfologia matematyczna

Dylacja z kwadratowym elementem strukturalnym 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h> 

using namespace std;
using namespace cv;

int main(){
  Mat dilated_img;
  Mat img = imread("./ship.jpg", 1 );
  cvtColor(img, img, CV_BGR2GRAY);
  threshold(img, img, 255, 255,THRESH_BINARY |THRESH_OTSU );

  for(int i = 1; i<10; i++){
    Mat structuring_element(2*i+1, 2*i+1, CV_8U, Scalar(1) );
    dilate( img, dilated_img, structuring_element );
    imshow( "Dilate", dilated_img );
  }  
  waitKey(0);
  return 0;  
}  

Dylacja z krzyżowym elementem strukturalnym 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h> 

using namespace std;
using namespace cv;

int main(){
  Mat dilated_img;
  Mat img = imread("./ship.jpg", 1 );
  cvtColor(img, img, CV_BGR2GRAY);
  threshold(img, img, 255, 255,THRESH_BINARY |THRESH_OTSU );

  for(int i = 1; i<10; i++){
    Mat element = getStructuringElement( MORPH_CROSS,
                                     Size( 2*i + 1, 2*i+1 ),
                                     Point( i, i) );
    dilate( img, dilated_img, element );
    imshow( "Dilate", dilated_img );
  }  
  waitKey(0);
  return 0;  
}  

Dylacja z kołowym elementem strukturalnym 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h> 

using namespace std;
using namespace cv;

int main(){
  Mat dilated_img;
  Mat img = imread("./ship.jpg", 1 );
  cvtColor(img, img, CV_BGR2GRAY);
  threshold(img, img, 255, 255,THRESH_BINARY |THRESH_OTSU );

  for(int i = 1; i<10; i++){
    Mat element = getStructuringElement( MORPH_ELLIPSE,
                                     Size( 2*i + 1, 2*i+1 ),
                                     Point( i, i) );
    dilate( img, dilated_img, element );
    imshow( "Dilate", dilated_img );
  }  
  waitKey(0);
  return 0;  
}  

Dylacja z eliptycznym elementem strukturalnym 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h> 

using namespace std;
using namespace cv;

int main(){
  Mat dilated_img;
  Mat img = imread("./ship.jpg", 1 );
  cvtColor(img, img, CV_BGR2GRAY);
  threshold(img, img, 255, 255,THRESH_BINARY |THRESH_OTSU );

  for(int i = 1; i<10; i++){
    Mat element = getStructuringElement( MORPH_ELLIPSE,
                                     Size( 2*i + 1, 4*i+1 ),
                                     Point( i, i) );
    dilate( img, dilated_img, element );
    imshow( "Dilate", dilated_img );
  }  
  waitKey(0);
  return 0;  
}  

Dylacja z róznymi elmentami strukturalnymi 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h> 

using namespace std;
using namespace cv;
Mat img; 
int dilation_elem = 0;
int dilation_size = 0;
int const max_elem = 2;
int const max_kernel_size = 21;
void dil(int, void* );
 
int main(){
  /// Read the image
  img = imread( "./ship.jpg", 1 );
  cvtColor(img, img, CV_BGR2GRAY);
  threshold(img, img, 255, 255,THRESH_BINARY |THRESH_OTSU );
 
  /// Create Trackbar to enter the number of bins
  namedWindow( "Source image", CV_WINDOW_AUTOSIZE );
 
  createTrackbar( "Element:", "Source image",
                  &dilation_elem, max_elem,
                  dil );

  createTrackbar( "Kernel size:", "Source image",
                  &dilation_size, max_kernel_size,
                  dil );
  dil(0,0);

  waitKey(0);
  return 0;
}
 
void dil(int, void* ){
  Mat dilated_img;
  int dilation_type;
  if( dilation_elem == 0 ){ dilation_type = MORPH_RECT; }
  else if( dilation_elem == 1 ){ dilation_type = MORPH_CROSS; }
  else if( dilation_elem == 2) { dilation_type = MORPH_ELLIPSE; }

  Mat element = getStructuringElement( dilation_type,
                                       Size( 2*dilation_size + 1, 10+2*dilation_size+1 ),
                                       Point( dilation_size, dilation_size ) );

  dilate( img, dilated_img, element );

  imshow( "Source image", dilated_img );
}

Dylacja z włsnym elementem strukturalnym 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h> 

using namespace std;
using namespace cv;

Mat circle(double r);

int main(){
  Mat dilated_img;
  Mat img = imread("./ship.jpg", 1 );
  cvtColor(img, img, CV_BGR2GRAY);
  threshold(img, img, 255, 255,THRESH_BINARY |THRESH_OTSU );

  Mat structuring_element = circle((double) 5);
  cout<< structuring_element << endl;
  dilate( img, dilated_img, structuring_element );
  
  imshow( "Binary", dilated_img );
  waitKey(0);
  return 0;  
}  

Mat circle(double r){
  Mat structuring_element( 2*r+1, 2*r+1, CV_8U, Scalar(1) );
  for(double i = 0 ; i < 2*r+1 ; i+=1){
    for(double j = 0 ; j < 2*r+1 ; j+=1){
      if(pow(i-r,2)+pow(j-r,2) > pow(r,2)){
        structuring_element.at<uchar>((int)i,(int)j)= 0;
      }
    }
  }
  return structuring_element;
}

Erozja z kwadratowym elementem strukturalnym 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h> 

using namespace std;
using namespace cv;

int main(){
  Mat erode_img;
  Mat img = imread("./ship.jpg", 1 );
  cvtColor(img, img, CV_BGR2GRAY);
  threshold(img, img, 255, 255,THRESH_BINARY |THRESH_OTSU );

  for(int i = 1; i<10; i++){
    Mat structuring_element(2*i+1, 2*i+1, CV_8U, Scalar(1) );
    erode( img, erode_img, structuring_element );
    imshow( "Erode", erode_img );
  }  
  waitKey(0);
  return 0;  
}  

Dylacja z krzyżowym elementem strukturalnym 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h> 

using namespace std;
using namespace cv;

int main(){
  Mat erode_img;
  Mat img = imread("./ship.jpg", 1 );
  cvtColor(img, img, CV_BGR2GRAY);
  threshold(img, img, 255, 255,THRESH_BINARY |THRESH_OTSU );

  for(int i = 1; i<10; i++){
    Mat element = getStructuringElement( MORPH_CROSS,
                                     Size( 2*i + 1, 2*i+1 ),
                                     Point( i, i) );
    erode( img, erode_img, element );
    imshow( "Dilate", erode_img );
  }  
  waitKey(0);
  return 0;  
}  

Dylacja z kołowym elementem strukturalnym 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h> 

using namespace std;
using namespace cv;

int main(){
  Mat erode_img;
  Mat img = imread("./ship.jpg", 1 );
  cvtColor(img, img, CV_BGR2GRAY);
  threshold(img, img, 255, 255,THRESH_BINARY |THRESH_OTSU );

  for(int i = 1; i<10; i++){
    Mat element = getStructuringElement( MORPH_ELLIPSE,
                                     Size( 2*i + 1, 2*i+1 ),
                                     Point( i, i) );
    erode( img, erode_img, element );
    imshow( "Dilate", erode_img );
  }  
  waitKey(0);
  return 0;  
}  

Dylacja z różnymi elementami strukturalnymi 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h> 

using namespace std;
using namespace cv;
 

Mat img; 
int erode_elem = 0;
int erode_size = 0;
int const max_elem = 2;
int const max_kernel_size = 21;
void erod(int, void* );
 
int main(){
  /// Read the image
  img = imread( "/home/przemek/Pulpit/openCVExamples/ship.jpg", 1 );
  cvtColor(img, img, CV_BGR2GRAY);
  threshold(img, img, 255, 255,THRESH_BINARY |THRESH_OTSU );
 
  /// Create Trackbar to enter the number of bins
  namedWindow( "Source image", CV_WINDOW_AUTOSIZE );
 
  createTrackbar( "Element:", "Source image",
                  &erode_elem, max_elem,
                  erod );

  createTrackbar( "Kernel size:", "Source image",
                  &erode_size, max_kernel_size,
                  erod );
  erod(0,0);

  waitKey(0);
  return 0;
}
 
void erod(int, void* ){
  Mat erode_img;
  int erode_type;
  if( erode_elem == 0 ){ erode_type = MORPH_RECT; }
  else if( erode_elem == 1 ){ erode_type = MORPH_CROSS; }
  else if( erode_elem == 2) { erode_type = MORPH_ELLIPSE; }

  Mat element = getStructuringElement( erode_type,
                                       Size( 2*erode_size + 1, 10+2*erode_size+1 ),
                                       Point( erode_size, erode_size ) );

  erode( img, erode_img, element );

  imshow( "Source image", erode_img );
}
 

Operacja otwarcia 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h> 

using namespace std;
using namespace cv;

int main(){
  Mat opened_img;
  Mat img = imread("./ship.jpg", 1 );
  cvtColor(img, img, CV_BGR2GRAY);
  threshold(img, img, 255, 255,THRESH_BINARY |THRESH_OTSU );

  Mat structuring_element( 5, 5, CV_8U, Scalar(1) );
  morphologyEx( img, opened_img, MORPH_OPEN, structuring_element );

  imshow( "Opene", opened_img );

  waitKey(0);
  return 0;  
}  

Operacja zamknięcia 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h> 

using namespace std;
using namespace cv;

int main(){
  Mat closed_img;
  Mat img = imread("./ship.jpg", 1 );
  cvtColor(img, img, CV_BGR2GRAY);
  threshold(img, img, 255, 255,THRESH_BINARY |THRESH_OTSU );

  Mat structuring_element( 5, 5, CV_8U, Scalar(1) );
  morphologyEx( img, closed_img, MORPH_CLOSE, structuring_element );

  imshow( "Close", closed_img );

  waitKey(0);
  return 0;  
}  

Operacja otwarcia z różnymi elementami strukturalnymi 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h> 
 
using namespace std;
using namespace cv;
 

Mat img; 
int opened_elem = 0;
int opened_size = 0;
int const max_elem = 2;
int const max_kernel_size = 41;
void open(int, void* );
 
int main(){
  /// Read the image
  img = imread( "./ship.jpg", 1 );
  cvtColor(img, img, CV_BGR2GRAY);
  threshold(img, img, 255, 255,THRESH_BINARY |THRESH_OTSU );
 
  /// Create Trackbar to enter the number of bins
  namedWindow( "Source image", CV_WINDOW_AUTOSIZE );
 
  createTrackbar( "Element:", "Source image",
                  &opened_elem, max_elem,
                  open );

  createTrackbar( "Kernel size:", "Source image",
                  &opened_size, max_kernel_size,
                  open );
  open(0,0);

  waitKey(0);
  return 0;
}
 
void open(int, void* ){
  Mat opened_img;
  int opened_type;
  if( opened_elem == 0 ){ opened_type = MORPH_RECT; }
  else if( opened_elem == 1 ){ opened_type = MORPH_CROSS; }
  else if( opened_elem == 2) { opened_type = MORPH_ELLIPSE; }

  Mat element = getStructuringElement( opened_type,
                                       Size( 2*opened_size + 1, 10+2*opened_size+1 ),
                                       Point( opened_size, opened_size ) );

  morphologyEx( img, opened_img, MORPH_OPEN, element );

  imshow( "Source image", opened_img );
}

Operacja zamknięcia z różnymi elementami strukturalnymi 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h> 
 
using namespace std;
using namespace cv;

Mat img; 
int closed_elem = 0;
int closed_size = 0;
int const max_elem = 2;
int const max_kernel_size = 51;
void close(int, void* );
 
int main(){
  /// Read the image
  img = imread( "/home/przemek/Pulpit/openCVExamples/ship.jpg", 1 );
  cvtColor(img, img, CV_BGR2GRAY);
  threshold(img, img, 255, 255,THRESH_BINARY |THRESH_OTSU );
 
  /// Create Trackbar to enter the number of bins
  namedWindow( "Source image", CV_WINDOW_AUTOSIZE );
 
  createTrackbar( "Element:", "Source image",
                  &closed_elem, max_elem,
                  close );

  createTrackbar( "Kernel size:", "Source image",
                  &closed_size, max_kernel_size,
                  close );
  close(0,0);

  waitKey(0);
  return 0;
}
 
void close(int, void* ){
  Mat closed_img;
  int closed_type;
  if( closed_elem == 0 ){ closed_type = MORPH_RECT; }
  else if( closed_elem == 1 ){ closed_type = MORPH_CROSS; }
  else if( closed_elem == 2) { closed_type = MORPH_ELLIPSE; }

  Mat element = getStructuringElement( closed_type,
                     Size( 2*closed_size + 1, 10+2*closed_size+1 ),
                      Point( closed_size, closed_size ) );

  morphologyEx( img, closed_img, MORPH_CLOSE, element );

  imshow( "Source image", closed_img );
}

Znajdowanie rogów za pomocą metody „Hit-or-Miss”. 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h> 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include 
#include 

using namespace std;
using namespace cv;

void hitmiss(Mat& img, Mat& dst, Mat& kernel);

int main(){
  Mat img_dst;
  Mat img_dst_1;
  Mat img_dst_2;
  Mat img_dst_3;
  Mat img_dst_4;
  Mat img = imread("./template1.png", 1 );
  cvtColor(img, img, CV_BGR2GRAY);
  threshold(img, img, 100, 255,THRESH_BINARY);
 
  Mat kernel_1 = (cv::Mat_(3,3) << 0, 1, 0, -1, 1, 1, -1, -1, 0);
  hitmiss(img, img_dst_1, kernel_1);

  Mat kernel_2 = (cv::Mat_(3,3) << 0, 1, 0, 1, 1, -1, 0, -1, -1);
  hitmiss(img, img_dst_2, kernel_2);

  Mat kernel_3 = (cv::Mat_(3,3) << 0, -1, -1, 1, 1, -1, 0, 1, 0);
  hitmiss(img, img_dst_3, kernel_3);

  Mat kernel_4 = (cv::Mat_(3,3) << -1, -1, 0, -1, 1, 1, 0, 1, 0);
  hitmiss(img, img_dst_4, kernel_4);

  imshow( "Binary", img );
  imshow( "Hit or Mis 1", img_dst_1 );
  imshow( "Hit or Mis 2", img_dst_2 );
  imshow( "Hit or Mis 3", img_dst_3 );
  imshow( "Hit or Mis 4", img_dst_4 );
  imshow( "Hit or Mis", img_dst_1|img_dst_2|img_dst_3|img_dst_4 );

  waitKey(0);
  return 0;  
}  

/**
 * Hit-or-miss transform function
 *
 * Parameters:
 *   img     The source image, 8 bit single-channel matrix
 *   dst     The destination image
 *   kernel  The kernel matrix. 1=foreground, -1=background, 0=don't care
 */
void hitmiss(cv::Mat& img, cv::Mat& dst, cv::Mat& kernel)
{
  CV_Assert(img.type() == CV_8U && img.channels() == 1);
  Mat img_copy;
  cv::Mat k1 = (kernel == 1) / 255;
  cv::Mat k2 = (kernel == -1) / 255;
  
  cv::normalize(img, img_copy, 0, 1, cv::NORM_MINMAX);
  cv::Mat e1, e2;
  cv::Mat ee1, ee2;

  cv::erode(img_copy, e1, k1);
  cv::erode(1-img_copy, e2, k2);
  dst = e1 & e2;
  cv::normalize(dst, dst, 0, 255, cv::NORM_MINMAX);
}

Pocienianie za pomocą metody „Hit-or-Miss”. 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h> 

void hitmiss(Mat& img, Mat& dst, Mat& kernel);

int main(){

  Mat img = imread("./template1.png", 1 );
  
  cvtColor(img, img, CV_BGR2GRAY);
  threshold(img, img, 100, 255,THRESH_BINARY);
  Mat img_dst = img.clone();
  Mat countdition;
  Mat prev;
  Mat img_temp;

  Mat kernel_1_1 = (Mat_(3,3) << -1, -1, -1, 0, 1, 0, 1, 1, 1);
  Mat kernel_1_2 = (Mat_(3,3) << 1, 0, -1, 1, 1, -1, 1, 0, -1);
  Mat kernel_1_3 = (Mat_(3,3) << 1, 1, 1, 0, 1, -1, -1, -1, -1);
  Mat kernel_1_4 = (Mat_(3,3) << -1, 0, 1, -1, 1, 1, -1, -1, 1);

  Mat kernel_2_1 = (Mat_(3,3) << 0, -1, -1, 1, 1, -1, 0, 1, 0);
  Mat kernel_2_2 = (Mat_(3,3) << 0, 1, 0, 1, 1, -1, 0, -1, -1);
  Mat kernel_2_3 = (Mat_(3,3) << 0, 1, 0, -1, 1, 1, -1, -1, 0);
  Mat kernel_2_4 = (Mat_(3,3) << -1, -1, 0, -1, 1, 1, 0, 1, 0);  

  do {
    prev = img_dst.clone();

    // the first pair of structural elements
    img_temp = img_dst.clone();
    hitmiss(img_temp, img_temp, kernel_1_1);
    absdiff(img_dst, img_temp, img_dst);
    img_temp = img_dst.clone();
    hitmiss(img_temp, img_temp, kernel_2_1);
    absdiff(img_dst, img_temp, img_dst);

    // the second pair of structural elements
    img_temp = img_dst.clone();
    hitmiss(img_temp, img_temp, kernel_1_2);
    absdiff(img_dst, img_temp, img_dst);
    img_temp = img_dst.clone();
    hitmiss(img_temp, img_temp, kernel_2_2);
    absdiff(img_dst, img_temp, img_dst);

    // the third pair of structural elements
    img_temp = img_dst.clone();
    hitmiss(img_temp, img_temp, kernel_1_3);
    absdiff(img_dst, img_temp, img_dst);
    img_temp = img_dst.clone();
    hitmiss(img_temp, img_temp, kernel_2_3);
    absdiff(img_dst, img_temp, img_dst);

    // the fourth pair of structural elements
    img_temp = img_dst.clone();
    hitmiss(img_temp, img_temp, kernel_1_4);
    absdiff(img_dst, img_temp, img_dst);
    img_temp = img_dst.clone();
    hitmiss(img_temp, img_temp, kernel_2_4);
    absdiff(img_dst, img_temp, img_dst);

    absdiff(img_dst, prev, countdition);
  } 
  while (countNonZero(countdition) > 0);

  imshow( "Binary", img );
  imshow( "Hit or Mis", img_dst );

  waitKey(0);
  return 0;  
}  

/**
 * Hit-or-miss transform function
 *
 * Parameters:
 *   img     The source image, 8 bit single-channel matrix
 *   dst     The destination image
 *   kernel  The kernel matrix. 1=foreground, -1=background, 0=don't care
 */
void hitmiss(cv::Mat& img, cv::Mat& dst, cv::Mat& kernel)
{
  CV_Assert(img.type() == CV_8U && img.channels() == 1);
  Mat img_copy;
  cv::Mat k1 = (kernel == 1) / 255;
  cv::Mat k2 = (kernel == -1) / 255;

  cv::normalize(img, img_copy, 0, 1, cv::NORM_MINMAX);
  cv::Mat e1, e2;

  cv::erode(img_copy, e1, k1, cv::Point(-1,-1), 1, cv::BORDER_CONSTANT, cv::Scalar(0));
  cv::erode(1-img_copy, e2, k2, cv::Point(-1,-1), 1, cv::BORDER_CONSTANT, cv::Scalar(0));
  dst = e1 & e2;
  cv::normalize(dst, dst, 0, 255, cv::NORM_MINMAX);
}

Pogrubienie za pomocą metody „Hit-or-Miss”. 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h> 

void hitmiss(Mat& img, Mat& dst, Mat& kernel);

int main(){
  Mat img = imread("./template1.png", 1 );
  cvtColor(img, img, CV_BGR2GRAY);
  threshold(img, img, 100, 255,THRESH_BINARY);
  Mat img_dst = img.clone();
  Mat countdition;
  Mat prev;
  Mat img_temp;

  Mat kernel_1_1 = (Mat_(3,3) << -1, -1, -1, 0, 1, 0, 1, 1, 1);
  Mat kernel_1_2 = (Mat_(3,3) << 1, 0, -1, 1, 1, -1, 1, 0, -1);
  Mat kernel_1_3 = (Mat_(3,3) << 1, 1, 1, 0, 1, -1, -1, -1, -1);
  Mat kernel_1_4 = (Mat_(3,3) << -1, 0, 1, -1, 1, 1, -1, -1, 1);

  Mat kernel_2_1 = (Mat_(3,3) << 0, -1, -1, 1, 1, -1, 0, 1, 0);
  Mat kernel_2_2 = (Mat_(3,3) << 0, 1, 0, 1, 1, -1, 0, -1, -1);
  Mat kernel_2_3 = (Mat_(3,3) << 0, 1, 0, -1, 1, 1, -1, -1, 0);
  Mat kernel_2_4 = (Mat_(3,3) << -1, -1, 0, -1, 1, 1, 0, 1, 0);  

  do {
    prev = img_dst.clone();

    // the first pair of structural elements
    img_temp = img_dst.clone();
    hitmiss(img_temp, img_temp, kernel_1_1);
    add(img_dst, img_temp, img_dst);
    img_temp = img_dst.clone();
    hitmiss(img_temp, img_temp, kernel_2_1);
    add(img_dst, img_temp, img_dst);

    // the second pair of structural elements
    img_temp = img_dst.clone();
    hitmiss(img_temp, img_temp, kernel_1_2);
    add(img_dst, img_temp, img_dst);
    img_temp = img_dst.clone();
    hitmiss(img_temp, img_temp, kernel_2_2);
    add(img_dst, img_temp, img_dst);

    // the third pair of structural elements
    img_temp = img_dst.clone();
    hitmiss(img_temp, img_temp, kernel_1_3);
    add(img_dst, img_temp, img_dst);
    img_temp = img_dst.clone();
    hitmiss(img_temp, img_temp, kernel_2_3);
    add(img_dst, img_temp, img_dst);

    // the fourth pair of structural elements
    img_temp = img_dst.clone();
    hitmiss(img_temp, img_temp, kernel_1_4);
    add(img_dst, img_temp, img_dst);
    img_temp = img_dst.clone();
    hitmiss(img_temp, img_temp, kernel_2_4);
    add(img_dst, img_temp, img_dst);

    absdiff(img_dst, prev, countdition);
  } 
  while (countNonZero(countdition) > 0);

  imshow( "Binary", img );
  imshow( "Hit or Mis", img_dst );

  waitKey(0);
  return 0;  
}  

/**
 * Hit-or-miss transform function
 *
 * Parameters:
 *   img     The source image, 8 bit single-channel matrix
 *   dst     The destination image
 *   kernel  The kernel matrix. 1=foreground, -1=background, 0=don't care
 */
void hitmiss(cv::Mat& img, cv::Mat& dst, cv::Mat& kernel)
{
  CV_Assert(img.type() == CV_8U && img.channels() == 1);
  Mat img_copy;
  cv::Mat k1 = (kernel == 1) / 255;
  cv::Mat k2 = (kernel == -1) / 255;

  cv::normalize(img, img_copy, 0, 1, cv::NORM_MINMAX);
  cv::Mat e1, e2;

  cv::erode(img_copy, e1, k1, cv::Point(-1,-1), 1, cv::BORDER_CONSTANT, cv::Scalar(0));
  cv::erode(1-img_copy, e2, k2, cv::Point(-1,-1), 1, cv::BORDER_CONSTANT, cv::Scalar(0));
  dst = e1 & e2;
  cv::normalize(dst, dst, 0, 255, cv::NORM_MINMAX);
}

Pogrubienie za pomocą metody „Hit-or-Miss”.