形态学滤波还可以进行边缘和角点的检测
边缘检测:
在形态学检测边缘时,可以使用opencv库中自带的函数morphologyEx,并将其中的参数设置为MORPH_GRADIENT
实现上,先定义一个MorphoFeatures类,getEdges方法通过morphologyEx函数可以很容易地得到边缘。代码如下:
class MorphoFeatures
{
private:
int threshold;
public:
void setThreshold(int t);
cv::Mat getEdges(const cv::Mat &image);
void applyThreshold(cv::Mat &result);
};
void MorphoFeatures::setThreshold(int t)
{
threshold = t;
}
cv::Mat MorphoFeatures::getEdges(const cv::Mat &image)
{
cv::Mat result;
cv::Mat element = cv::getStructuringElement(0,
cv::Size(5, 5),
cv::Point(3, 3));
cv::morphologyEx(image, result, cv::MORPH_GRADIENT, element);
applyThreshold(result);
return result;
}
void MorphoFeatures::applyThreshold(cv::Mat &result)
{
if (threshold > 0)
{
cv::threshold(result, result, threshold, 255, cv::THRESH_BINARY);
}
}
int main()
{
cv::Mat image = cv::imread("F:\\building.jpg", 0);
MorphoFeatures morpho;
morpho.setThreshold(80);
cv::Mat edges;
edges = morpho.getEdges(image);
cv::imshow("1", edges);
cv::waitKey(0);
return 0;
}
即可很容易得到边缘图片
角点检测:
由于opencv没有直接实现形态学检测角点,因而我们需要使用非方形结构,包括菱形、十字、X型等等,这在类中会有体现。
在MorphoFeatures类的最开始,使用重构,初始化private中的变量;然后再进行创建元素
原理想法:
如果将图像以灰度图的形式显示, 那么边缘可以看作是明亮和灰暗像素的快速过渡,可以看作陡峭的悬崖
因而,在角点检测的时候,可以采取:
十字膨胀+菱形腐蚀->结果1
X型膨胀+方形腐蚀->结果2
二者相减得到角点图片
(具体原理等我搞明白数学之后补充)
在这之后,我改动了书上的代码,使用了另一种形式:
采用二值化图像+0判断选取角点,具体代码如下:
MorphoFeatures类:
class MorphoFeatures
{
private:
int threshold;
cv::Mat cross;
cv::Mat diamond;
cv::Mat square;
cv::Mat x;
public:
void setThreshold(int t);
cv::Mat getEdges(const cv::Mat &image);
void applyThreshold(cv::Mat &result);
MorphoFeatures():threshold(-1), cross(5, 5, CV_8U, cv::Scalar(0)),
diamond(5, 5, CV_8U, cv::Scalar(1)),
square(5, 5, CV_8U, cv::Scalar(1)),
x(5, 5, CV_8U, cv::Scalar(0))
{
for (int i = 0; i<5; i++)
{
cross.at
cross.at
}
diamond.at
diamond.at
diamond.at
diamond.at
diamond.at
diamond.at
diamond.at
diamond.at
diamond.at
diamond.at
diamond.at
diamond.at
for (int i = 0; i<5; i++) {
x.at
x.at
}
}
cv::Mat getCorners(const cv::Mat &image);
void drawOnImage(const cv::Mat& binary, cv::Mat& image);
};
MorphoFeatures的cpp:
void MorphoFeatures::setThreshold(int t)
{
threshold = t;
}
cv::Mat MorphoFeatures::getEdges(const cv::Mat &image)
{
cv::Mat result;
cv::Mat element = cv::getStructuringElement(0,
cv::Size(5, 5),
cv::Point(3, 3));
cv::morphologyEx(image, result, cv::MORPH_GRADIENT, element);
applyThreshold(result);
return result;
}
void MorphoFeatures::applyThreshold(cv::Mat &result)
{
if (threshold > 0)
{
cv::threshold(result, result, threshold, 255, cv::THRESH_BINARY);
}
}
cv::Mat MorphoFeatures::getCorners(const cv::Mat &image)
{
cv::Mat result;
cv::dilate(image, result, cross);
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;
}
void MorphoFeatures::drawOnImage(const cv::Mat& binary, cv::Mat& image)
{
for (int i = 0; i < binary.rows; i++)
{
for (int j = 0; j < binary.cols; j++)
{
if (binary.at
{
cv::circle(image, cv::Point(j, i), 5, cv::Scalar(255, 0, 0));
}
}
}
}
主函数:
int main()
{
cv::Mat image = cv::imread("F:\\building.jpg", 0);
cv::Mat image2 = cv::imread("F:\\building.jpg");
cv::Mat corners;
cv::Mat twoValue;
MorphoFeatures morpho;
corners = morpho.getCorners(image);
cv::imshow("1", corners);
cv::threshold(corners, twoValue, 30, 255, 0);
morpho.drawOnImage(twoValue, image2);
cv::imshow("12", image2);
cv::waitKey(0);
return 0;
}
先这样吧,接着看数学了。。