计算机视觉讨论群162501053
转载请注明:http://blog.csdn.net/abcd1992719g
收入囊中
- 利用OpenCV函数进行形态学梯度操作
- 自定义结构矩阵进行形态学梯度操作
葵花宝典
在此之前,如果你还没接触过灰度图像形态学膨胀与腐蚀,希望你能仔细阅读
灰度图像形态学膨胀与腐蚀
本质上,灰度与二值并不差异,二值不过是0与255,膨胀与腐蚀的操作都是一样的
形态学梯度的定义如下:
形态梯度
dst=morph_grad(src,element)=dilate(src,element)-erode(src,element)
通俗讲,dilate是膨胀操作,相当于把图像稍微变胖,灰度阶梯变高,erode相当于把图像变稍微细一点,两个相减,就产生了边缘。
我在
Computer Vision: Algorithms and ApplicationsのImage processing 里对形态学操作有简单的介绍。
初识API
C++:
Mat
getStructuringElement
(
int
shape
, Size
ksize
, Point
anchor
=Point(-1,-1)
)
这个函数用来获得结构矩阵
shape:
MORPH_RECT - 矩形的结构元素:值全为1
MORPH_ELLIPSE - 椭圆形结构元素
MORPH_CROSS - 十字形,只有中心在的那一行一列的值为1
ksize:结构元素的大小
anchor:默认(-1,-1),指代中心,只有十字形元素才依赖这个
-
C++:
void
dilate
(InputArray
src, OutputArray
dst, InputArray
kernel, Point
anchor=Point(-1,-1), int
iterations=1, int
borderType=BORDER_CONSTANT, const Scalar&
borderValue=morphologyDefaultBorderValue()
)
-
- src – 输入图像
- dst – 输出图像
- element – 结构元素.如果 element=Mat() , 一个3*3的结构元素就被使用
- anchor – 同上
- iterations – 迭代次数
- borderType – 边界类型,我在Computer Vision: Algorithms and ApplicationsのImage processing讨论过
- borderValue – 边界值,当边界类型为常数填充时启用
(膨胀公式,灰度图像形态学膨胀与腐蚀此文都有介绍)
腐蚀操作对应的API erode和膨胀是一样的
其他形态学操作函数
-
C++:
void
morphologyEx
(InputArray
src, OutputArray
dst, int
op, InputArray
kernel, Point
anchor=Point(-1,-1), int
iterations=1, int
borderType=BORDER_CONSTANT, const Scalar&
borderValue=morphologyDefaultBorderValue()
)
-
其他的参数和腐蚀,膨胀是一样的- op – 操作类型,今天我们只关注梯度,也就是第3个
- MORPH_OPEN - an opening operation
- MORPH_CLOSE - a closing operation
- MORPH_GRADIENT - a morphological gradient
- MORPH_TOPHAT - “top hat”
- MORPH_BLACKHAT - “black hat”
- op – 操作类型,今天我们只关注梯度,也就是第3个
Morphological gradient:
荷枪实弹
先介绍一个类
class MorphoFeatures {
private:
int threshold; //用于阀值操作
void applyThreshold(Mat& result) {
if (threshold>0)
cv::threshold(result, result,threshold, 255, THRESH_BINARY_INV); //注意参数是THRESH_BINARY_INV,当<threshold为255,否则为0,倒过来了
}
public:
void setThreshold(int x) {
threshold = x;
}
Mat getEdges(const Mat &image) {
Mat result;
morphologyEx(image,result,MORPH_GRADIENT,Mat()); //直接调用,默认3*3
applyThreshold(result);
return result;
}
};
我们的主函数
int main( int, char** argv )
{
Mat image;
image = imread( argv[1] );
cvtColor( image, image, CV_RGB2GRAY );
MorphoFeatures morpho;
morpho.setThreshold(40);
Mat edges;
edges= morpho.getEdges(image);
namedWindow("dstImage", 1);
imshow("dstImage", edges);
waitKey();
return 0;
}
效果图:
我们再基于公式自己实现一下,修改的地方很少,主函数没有变化(不一样的地方有注释)
class MorphoFeatures {
private:
int threshold;
Mat structedElement; //自己定义的结构矩阵
void applyThreshold(Mat& result) {
if (threshold>0)
cv::threshold(result, result,threshold, 255, THRESH_BINARY_INV);
}
public:
MorphoFeatures() : structedElement(3,3,CV_8U,Scalar(1)){} //没有使用API而是直接构造
void setThreshold(int x) {
threshold = x;
}
Mat getEdges(const Mat &image) {
Mat result,result1,result2;
dilate(image,result1,structedElement); //先膨胀
erode(image,result2,structedElement); //再腐蚀
result = result1 - result2; //然后相减
applyThreshold(result);
return result;
}
};
效果图:好像一样哦
举一反三
习惯了用矩形的结构元素,我们用椭圆试一试吧
代码改的地方也很少,为了方便大家,这个代码就全部发出来了
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
class MorphoFeatures {
private:
int threshold;
Mat structedElement;
void applyThreshold(Mat& result) {
if (threshold>0)
cv::threshold(result, result,threshold, 255, THRESH_BINARY_INV);
}
public:
MorphoFeatures() {
structedElement = getStructuringElement( MORPH_ELLIPSE, Size( 3, 3 ));
}
void setThreshold(int x) {
threshold = x;
}
Mat getEdges(const Mat &image) {
Mat result,result1,result2;
dilate(image,result1,structedElement);
erode(image,result2,structedElement);
result = result1 - result2;
applyThreshold(result);
return result;
}
};
int main( int, char** argv )
{
Mat image;
image = imread( argv[1] );
cvtColor( image, image, CV_RGB2GRAY );
MorphoFeatures morpho;
morpho.setThreshold(40);
Mat edges;
edges= morpho.getEdges(image);
namedWindow("dstImage", 1);
imshow("dstImage", edges);
waitKey();
return 0;
}