要点
1.图像膨胀/腐蚀
2.直线检测(hough变换)
数学形态学的简单应用
解释
1.图像膨胀/腐蚀
腐蚀与膨胀,概念自行参考
2.直线检测(hough变换)
来一段套路熟悉下这是个什么鬼?
Hough变换是图像处理中的一种特征提取技术,该过程在一个参数空间中通过计算累计结果的局部最大值得到一个符合该特定形状的集合作为Hough变换的结果。简单而言就是运用两个坐标之前的变换将在一个空间中具有相同形状的曲线或直线映射到另一个坐标空间的一个点上形成峰值,从而把检测任意形状的问题转换为统计峰值的问题。
tip:在使用Hough变换之前,首先要对图像进行边缘检测,Hough变换的直线输入只能是边缘二值图像。
3.形态学的简单应用
利用各个不同的结构体进行膨胀和腐蚀以达到一个角点检测的目的。
(千言万语不如代码能说明问题)
程序
1.膨胀/腐蚀
#include <opencv2\opencv.hpp>
#include <iostream>
using namespace cv;
int main()
{
Mat srcImage = imread("F:\\c_code\\week6_3\\week6_3\\1.png",0);
imshow("src", srcImage);
Size s1(5, 5);
Mat element = getStructuringElement(MORPH_RECT, s1);
std::cout << s1 << std::endl;
Mat out;
Mat dilateOut;
dilate(srcImage, dilateOut, element);
erode(srcImage, out, element);
imshow("erode", out);
imshow("dilate", dilateOut);
Mat afterErodeSub = srcImage - out;
Mat afterDilateSub = dilateOut - srcImage;
imshow("subDilate", afterDilateSub);
imshow("subErode", afterErodeSub);
waitKey(0);
return 0;
}
仅放三张图示意一下,还有做出的差值图像显示边缘,5*5的结构体。这些结果请自行查看。
Hough变换
#include <opencv2\opencv.hpp>
#include <iostream>
using namespace cv;
int main(int argc, char** argv)
{
Mat srcImage = imread("F:\\c_code\\week7_2\\week7_2\\5.png");
Mat midImage, dstImage;
Canny(srcImage, midImage, 50, 200, 3);
cvtColor(midImage, dstImage, CV_GRAY2BGR);
vector<Vec4i> lines;
HoughLinesP(midImage, lines, 1, CV_PI / 180, 180, 50, 10);
for (size_t i = 0; i < lines.size(); i++)
{
Vec4i l = lines[i];
line(dstImage, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 2, CV_AA);
}
imshow("srcImage", srcImage);
imshow("cannyImage", midImage);
imshow("result", dstImage);
waitKey(0);
return 0;
}
这个阈值调起来比较麻烦一点。。。
3.简单应用
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv/cv.h>
using namespace std;
using namespace cv;
class MorphoFeatures{
private:
//用于生成二值图像的阈值
int ithreshold;
//角点检测中用到的结构元素
Mat cross;
Mat diamond;
Mat square;
Mat x;
void applyThreshold(Mat &result);
public:
MorphoFeatures() :ithreshold(50), cross(5, 5, CV_8U, Scalar(0)), diamond(5, 5, CV_8U, Scalar(1)), square(5, 5, CV_8U, Scalar(1)), x(5, 5, CV_8U, Scalar(0)){
//创建十字形元素
for (int i = 0; i < 5; i++)
{
cross.at<uchar>(2, i) = 1;
cross.at<uchar>(i, 2) = 1;
}
//创建菱形元素
diamond.at<uchar>(0, 0) = 0;
diamond.at<uchar>(0, 1) = 0;
diamond.at<uchar>(1, 0) = 0;
diamond.at<uchar>(4, 4) = 0;
diamond.at<uchar>(3, 4) = 0;
diamond.at<uchar>(4, 3) = 0;
diamond.at<uchar>(4, 0) = 0;
diamond.at<uchar>(4, 1) = 0;
diamond.at<uchar>(3, 0) = 0;
diamond.at<uchar>(0, 4) = 0;
diamond.at<uchar>(0, 3) = 0;
diamond.at<uchar>(1, 4) = 0;
//创建x形元素
for (int i = 0; i < 5; i++)
{
x.at<uchar>(i, i) = 1;
x.at<uchar>(4 - i, i) = 1;
}
}
Mat getEdges(const Mat &image);
void setThreshold(float t);
Mat getCorners(const Mat&image);
void drawOnImage(const Mat &binary, Mat &image);
};
//获取二值的边缘图像
void MorphoFeatures::applyThreshold(Mat &result){
//使用阈值化
if (ithreshold > 0)
{
threshold(result, result, ithreshold, 255, THRESH_BINARY);
}
}
//morphologyEx + 合适的滤波器实现直线的检测
Mat MorphoFeatures::getEdges(const Mat &image){
//得到梯度图
Mat result;
morphologyEx(image, result, MORPH_GRADIENT, Mat());
//阈值化以得到二值图像
applyThreshold(result);
return result;
}
//设置直方图的阈值[0,1]
void MorphoFeatures::setThreshold(float t){
ithreshold = t;
}
//连接使用这些结构以得到最终的角点映射图
Mat MorphoFeatures::getCorners(const Mat&image){
Mat result;
//十字形膨胀
dilate(image, result, cross);
//菱形腐蚀
erode(result, result, diamond);
Mat result2;
//X形膨胀
dilate(image, result2, x);
//方形腐蚀
erode(result2, result2, square);
//通过对两张图像做差值得到角点图像
absdiff(result2, result, result);
//阈值化以得到二值图像
applyThreshold(result);
return result;
}
//在二值图像中的每个检测点上绘制一个圆 更好的可视化结果
void MorphoFeatures::drawOnImage(const Mat &binary, Mat &image){
Mat_<uchar>::const_iterator it = binary.begin<uchar>();
Mat_<uchar>::const_iterator itend = binary.end<uchar>();
//遍历每个像素
for (int i = 0; it != itend; ++it, ++i)
{
if (*it)
circle(image, Point(i%image.step, i / image.step), 5, Scalar(255, 0, 0));
}
}
int main(){
Mat image = cvLoadImage("F:\\c_code\\week7_3_new\\week7_3_new\\1.png");
Mat grayImage;
cvtColor(image, grayImage, CV_BGR2GRAY);
//显示原图
namedWindow("Image");
imshow("Image", grayImage);
MorphoFeatures morpho;
//得到角点
Mat corners;
corners = morpho.getCorners(grayImage);
//在图像中显示角点
morpho.drawOnImage(corners, grayImage);
namedWindow("Corners on Image");
imshow("Corners on Image", grayImage);
waitKey(0);
return 0;
}
草草结束。。。。(好不容易考完了泛函,接下来该认真做事了)
放一张美照结束