(原创)基于matlab和c++混合实现的SUSAN特征检测

/
//简述:用MATLAB获取圆周模板,自定义封装susan的特征提取函数(GetUSAN),实现对图像的SUSAN特征检测,
//      关于SUSAN特征的原理请参考:https://blog.csdn.net/kezunhai/article/details/11269793。
//作者:Ephemeroptera
//地点:安徽大学
//最后修改时间:2018-11-20
//联系QQ:605686962
/
#include<opencv2\opencv.hpp>
#include <iostream>
#include "engine.h"
#include"susan.h"

using namespace cv;
using namespace std;

int Multmax(int n, ...); // 定义多个变量的最大值提取
int main()
{
	const uchar radius = 3;//本例选取半径为3即(7x7)的圆周模板

	/*-----------------------------------进入MATLAB工作空间--------------------------------------------*/
	Engine *ep = NULL;                                    //申明引擎指针
	if (!(ep = engOpen(""))) {                             //指向matlab工作空间
		fprintf(stderr, "\nCan't start MATLAB engine\n");
		return EXIT_FAILURE;
	}
	//在matlab引擎中执行matlab命令
	engEvalString(ep, "template=fspecial('disk',3);%取7x7的圆周模板");
	engEvalString(ep, "template(template>min(template(template>0)))=1;  %模板二值化");
	engEvalString(ep, "template(template<1)=0;");
	engEvalString(ep, "[x,y]=find(template==1)%获取偏移地址");
	//取出matlab工作空间中变量
	mxArray* x = engGetVariable(ep, "x");
	mxArray* y = engGetVariable(ep, "y");
	//保存入c++向量中
	std::vector<Point2i> offset;
	double* p = mxGetPr(x);              //实部指针
	double* q = mxGetPr(y);
	size_t offsetNum = mxGetNumberOfElements(x);   //统计偏移地址个数个数
	while (offsetNum > 0)                       //保存入向量中
	{
		offset.push_back(Point2i((int)*p++-radius-1, (int)*q++-radius-1));
		--offsetNum;
	}
	cout << "圆周模板的偏移向量是:" << offset << endl;

	/*-----------------------------------对图像的掩模处理--------------------------------------------*/
	Mat RGB = imread("man.jpg");        //读取图片(RGB)
	imshow("Original IMG", RGB);
	Mat GRAY(RGB.size(), CV_8UC1);
	cvtColor(RGB, GRAY, CV_BGR2GRAY);   //灰度化(GRAY)      
	Mat USAN = Mat::zeros(RGB.size(), CV_8UC1);//定义USAN记录掩模滑动中USAN的值
	GetUSAN(USAN, GRAY, offset, radius, 30,1/4.0);  //空域处理,susan检测;这里是作者自己写的susan特征提取函数,
	                                                //有需要的同学可点击(https://download.csdn.net/download/ephemeroptera/10796926)下载
	Mat BIN = USAN > 0;         //USAN二值化
	imshow("SUSAN to EDGE", BIN);

	/*-----------------------------------角点检测(非极大值抑制)--------------------------------------------*/
	std::vector<Point2i> corners;  //定义角点
	
	//对USAN遍历寻找极大值
		for (int i = 1; i <= USAN.rows - 2; ++i)
			for (int j = 1; j <= USAN.cols - 2; ++j)
			{
				//  该值大于8邻域值则判定为极大值
				if (*USAN.ptr(i,j) > Multmax(8, *USAN.ptr(i - 1, j - 1), *USAN.ptr(i + 1, j + 1),
					*USAN.ptr(i - 1, j + 1), *USAN.ptr(i + 1, j - 1),
					*USAN.ptr(i, j - 1), *USAN.ptr(i, j + 1),
					*USAN.ptr(i - 1, j), *USAN.ptr(i + 1, j)))
				{
					corners.push_back(Point2i(i, j));  //收纳极大值(corners)
					circle(RGB,Point(j,i), 1, Scalar(0, 0, 255), -1);//标记SUSAN特征
				}

			}			
	namedWindow("SUSAN to CORNERS", WINDOW_NORMAL);
	imshow("SUSAN to CORNERS", RGB);
	waitKey(0);
	return 0;

}
int Multmax(int n, ...)  // 定参 n 表示后面变参数量,定界用,输入时切勿搞错
{
	va_list ap;       // 定义一个 va_list 指针来访问参数表
	va_start(ap, n);     // 初始化 ap,让它指向第一个变参
	int maximum = -0x7FFFFFFF;   // 这是一个最小的整数
	int temp;
	for (int i = 0; i < n; i++)
	{
		temp = va_arg(ap, int);   // 获取一个 int 型参数,并且 ap 指向下一个参数
		if (maximum < temp)
			maximum = temp;
	}
	va_end(ap);       // 善后工作,关闭 ap
	return maximum;
}


附上生成结果:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ephemeroptera

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值