学习OpenCV(七)

使用形态滤波器侵蚀和膨胀图像

1、函数cv::erode()

     默认使用3*3矩阵处理二值图像,其作用是用核心矩阵处理图像,替换矩阵所覆盖区域的像素值为这个区域的最小值,也即图像处理后白色可能会减少。

2、函数cv::dilate()

     作用和cv::erode()相反

3、自定义核心矩阵

cv::Mat element(7,7,CV_8U,cv::Scalar(1));
cv::erode(image,eroded,element);

4、同一核心矩阵多次操作

cv::erode(image,eroded,cv::Mat(),cv::Point(-1,-1),3);

使用形态滤波器Opening和Closeing图像

1、关闭操作

cv::Mat element1(5 , 5 , CV_8U , cv::Scalar(1)) ;
	cv::Mat closed ;
	//cv::Mat closed1 ;

	cv::morphologyEx(image , closed , cv::MORPH_CLOSE , element1) ;
	//cv::dilate(image , closed1 , element1) ;//这两步等价于以上一步
	//cv::erode(closed1 , closed1 , element1) ;

2、打开操作

     类似关闭操作

注意:opened和closed可以依次使用获得不同的效果比如先使用closed在使用opened可以获得图像中的主要Object。

参考: 《opencv cookbook》P120


使用形态滤波器检测图像中的边界和角:

cv::Mat getEdges(const cv::Mat &image)
	{
		cv::Mat result ;
		cv::morphologyEx(image , result , cv::MORPH_GRADIENT , cv::Mat()) ;
		applyThreshold(result) ;
		return result ;
	}

cv::Mat getCorners(const cv::Mat &image)
	{
		cv::Mat result ;
		cv::dilate(image , result , cross) ;//相当于Closing
		cv::erode(result , result , diamond) ;

		cv::Mat result2 ;
		cv::dilate(image , result2 , x) ;
		cv::erode(result2 , result2 , square) ;

		cv::absdiff(result2 , result , result) ;
		applyThreshold(result) ;
		return result ;
	}
cv::morphologyEx(corners,corners,cv::MORPH_TOPHAT,cv::Mat());
	cv::threshold(corners, corners, 40, 255, cv::THRESH_BINARY_INV);

标记出角:

void drawOnImage(const cv::Mat &binary , cv::Mat & image)
	{
		cv::Mat_<uchar>::const_iterator it = binary.begin<uchar>() ;
		cv::Mat_<uchar>::const_iterator itend = binary.end<uchar>() ;

		for(int i = 0 ; it != itend ; ++it , ++i)
		{
			if(!*it)
			{
				cv::circle(image , 
					cv::Point(i % image.step , i / image.step) ,
					5 , cv::Scalar(255 , 0 , 0))  ;
			}
		}
	}

图像分割分水岭法程序:

思路参考:《OpenCV中分割图像的分水岭法

头文件:

#pragma once

#include "highgui.h"
#include <imgproc\imgproc.hpp>

class WatershedSegmenter
{
private:
	cv::Mat markers ;
public:
	void setMarkers(const cv::Mat & markerImage)
	{
		//把标记markerImage的值变成有符号的32位数存在三种值128 , 255 ,0,其中
		//128 , 255分别代表一种区域,0为未知区域也即需要把0分给以上两种
		markerImage.convertTo(markers , CV_32S) ;
	}

	cv::Mat process(const cv::Mat & image)
	{
		cv::watershed(image , markers) ;
		return markers ;
	}

	cv::Mat getSegmentation()
	{
		cv::Mat tmp ;
		markers.convertTo(tmp , CV_8U) ;
		return tmp ;
	}

	cv::Mat getWatersheds()
	{
		cv::Mat tmp ;
		//只得到两种值0 , 255(黑白),-1(分水岭)置为0,其他为255
		markers.convertTo(tmp , CV_8U , 255 , 255) ;
		return tmp ;
	}
};

源文件:

/*
*
*Function:使用分水岭法分割图像
*
**/
#pragma  once
#include "highgui.h"
#include "imgproc\imgproc.hpp"
#include "WatershedSegmenter.h"
#include <stdio.h>

int main()
{
	cv::Mat binary = cv::imread("D:/Development/OpenCV/images/binary.bmp" , 0) ;
	cv::imshow("original" , binary) ;

	cv::Mat fg ;
	cv::erode(binary , fg , cv::Mat() , cv::Point(-1 , -1) , 6) ;
	cv::imshow("fg" , fg) ;

	cv::Mat bg ;
	cv::dilate(binary , bg , cv::Mat() , cv::Point(-1 , -1) , 6) ;
	cv::imshow("bg_1" , bg) ;
	cv::threshold(bg , bg , 1 , 128 , cv::THRESH_BINARY_INV) ;
	cv::imshow("bg_2" , bg) ;

	cv::Mat markers(binary.size() , CV_8U , cv::Scalar(0)) ;
	markers = fg + bg ;
	cv::imshow("markers" , markers) ;

	cv::imwrite("D:/Development/OpenCV/images/markers.bmp" , markers) ;

	cv::Mat image = cv::imread("D:/Development/OpenCV/images/group.jpg") ;

 	WatershedSegmenter segmenter ;
 	segmenter.setMarkers(markers) ;
 	segmenter.process(image) ;

	cv::imshow("Segmenters" , segmenter.getSegmentation()) ;
	cv::imwrite("D:/Development/OpenCV/images/segmenters.bmp" ,segmenter.getSegmentation() );
	cv::imshow("Watersheds" , segmenter.getWatersheds()) ;
	cv::imwrite("D:/Development/OpenCV/images/watersheds.bmp" ,segmenter.getWatersheds() );

	cv::waitKey(0) ;

	return 0 ;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值