首页 > 编程知识 正文

opencv矩形轮廓检测,opencv轮廓检测和匹配

时间:2023-05-05 15:09:51 阅读:163498 作者:4199

关于Learning Opencv 3 ——第十四章轮廓匹配Opencv轮廓的介绍可以参考https://blog.csdn.net/a 40850273/article/details/88063478

Moments Moments是轮廓、图像和点的高级特征,计算方法如下

这可以看作是对图像中各像素点的加权和,如果是,则各像素点的权重为1。 对于像素值既不是1也不是0的二值图像,为非零像素值的面积。 如果有轮廓,就是轮廓的长度。 同样,除以和表示图像的x方向和y方向的平均值。

cv:Moments ()用于计算图像的moments

cv : moments cv : moments//returnstructurecontainsmomentscv 33603360 inputarraypoints,//2-dimensionalpoints

points维数组(单张图像)或多点)单个轮廓(binaryImage )如果为True,则所有非零像素值都将被视为大于或等于1,并且所需的Moments将根据轮廓的缩放和旋转而变化。

满足平移不变性的中心 Moments

图像或轮廓具有平移不变性。 但是,更高级别的Moments将不再具有这个特征。 中心Moments的定义如下

其中,

通过对各像素点相对于其中心进行求解成功地满足了平移不变性。 其中,很明显可以得到。

同时满足缩放不变性的归一化中心 Moments

另外,为了引入定标不变性,引入正规化中心Moments,定义如下

满足旋转不变性的Hu invariant moments

Hu invariant Moments由规格化中心moments线性组合,以提供缩放、旋转和反射(反射不令人满意)的不变性。

计算的例子如下所示

void cv :3360 Hu moments (const cv : moments moments,//inputisresultfromcv 33603360 moments ) function double * Hu cv 3333333330

使用Hu Moments的匹配cv:matchShapes ()根据提供的两个目标自动计算Moments,并根据最后用户提供的标准进行比较。

double cv :3360匹配形状(cv :3360 inputarrayobject 1,/firstarrayof2dpointsorcv : u 8c1 image cv 33603360 inputarrray//secondarrayof2dpointsorcv 3360 u 8c1 imageintmethod,//comparparage 参数说明:

object1、object2:输入的两个目标必须是灰度图像或轮廓method。 匹配方法有以下三种,不同的method会影响最后返回的匹配度。

parameter :未使用当前算法,可以轻松使用初始值。 该参数可以主要通过使用定制参数使用形状上下文比较形状的Moments来进行形状匹配以适应将来新添加的method,并且可以追溯到80年代。 另外,虽然最新的算法层出不穷,但是目前的Shape模块还在开发中,所以这里只简单介绍一下上层的接口。

Shape模块的结构Shape的构建基于抽象类cv : shapedistanceextractor。 返回一个非负的数字。 如果两个形状完全相同,则返回0。

classshapecontextdistanceextractor : publicshapedistanceextractor { public : virtualfloatcomputedistance (inputarrayce )

0;};

而具体的形状距离提取类将派生自这个基类 cv::ShapeDistanceExtractor。这里简要介绍其中的两个 cv::ShapeTransformer 和 cv::HistogramCostExtractor。

class ShapeTransformer : public Algorithm {public: virtual void estimateTransformation( cv::InputArray transformingShape, cv::InputArray targetShape, vector<cv::DMatch>& matches ) = 0; virtual float applyTransformation( cv::InputArray input, cv::OutputArray output = noArray() ) = 0; virtual void warpImage( cv::InputArray transformingImage, cv::OutputArray output, int flags = INTER_LINEAR, int borderMode = BORDER_CONSTANT, const cv::Scalar& borderValue = cv::Scalar() ) const = 0;};class HistogramCostExtractor : public Algorithm {public: virtual void buildCostMatrix( cv::InputArray descriptors1, cv::InputArray descriptors2, cv::OutputArray costMatrix ) = 0; virtual void setNDummies( int nDummies ) = 0; virtual int getNDummies() const = 0; virtual void setDefaultCost( float defaultCost ) = 0; virtual float getDefaultCost() const = 0;};

shape transformer 表示了从一堆点到另一堆点再映射算法的类,其中仿射变换和透视变换都可以用形状变换实现(在 Opencv 中 cv::ThinPlateSplineShapeTransformer)。

histogram cost extractor 映射直方图中一个格到另一个格的 shoveling dirt 为一个代价。常用的派生类如下

对于每一个 extractors 和 transformers 都存在一个工厂方法(createX()),比如 cv::createChiHistogramCostExtractor()。

shape context distance extractor namespace cv { class ShapeContextDistanceExtractor : public ShapeDistanceExtractor { public: ... virtual float computeDistance( InputArray contour1, InputArray contour2 ) = 0; }; Ptr<ShapeContextDistanceExtractor> createShapeContextDistanceExtractor( int nAngularBins = 12, int nRadialBins = 4, float innerRadius = 0.2f, float outerRadius = 2, int iterations = 3, const Ptr<HistogramCostExtractor> &comparer = createChiHistogramCostExtractor(), const Ptr<ShapeTransformer> &transformer = createThinPlateSplineShapeTransformer() );}

本质上 Shape Context algorithm 计算两个或更多的待比较物体的表征。每一个表征基于形状边缘的一系列子级点,同时对于每一个采样点,它构造一个确定的直方图来反映从该点角度在极坐标系下的形状。所有的直方图具有相同的大小 nAngularBins * nRadialBins。两个待匹配物体上的点基于 chi-squared 计算距离。然后算法计算两个待匹配物体最优的 1:1 点匹配从而得到最小的 chi-squared 距离总和。这个算法不算快,不过能够提供一个相对不错的结果。

#include "opencv2/opencv.hpp"#include <algorithm>#include <iostream>#include <string>using namespace std;using namespace cv;static vector<Point> sampleContour( const Mat& image, int n=300 ) { vector<vector<Point> > _contours; vector<Point> all_points; findContours(image, _contours, RETR_LIST, CHAIN_APPROX_NONE); for (size_t i=0; i <_contours.size(); i++) { for (size_t j=0; j <_contours[i].size(); j++) all_points.push_back( _contours[i][j] ); // If too little points, replicate them// int dummy=0; for (int add=(int)all_points.size(); add<n; add++) all_points.push_back(all_points[dummy++]); // Sample uniformly random_shuffle(all_points.begin(), all_points.end()); vector<Point> sampled; for (int i=0; i<n; i++) sampled.push_back(all_points[i]); return sampled;}int main(int argc, char** argv) { string path = "../data/shape_sample/"; int indexQuery = 1; Ptr<ShapeContextDistanceExtractor> mysc = createShapeContextDistanceExtractor(); Size sz2Sh(300,300); Mat img1=imread(argv[1], IMREAD_GRAYSCALE); Mat img2=imread(argv[2], IMREAD_GRAYSCALE); vector<Point> c1 = sampleContour(img1); vector<Point> c2 = sampleContour(img2); float dis = mysc->computeDistance( c1, c2 ); cout << "shape context distance between " << argv[1] << " and " << argv[2] << " is: " << dis << endl; return 0;} Hausdorff distance extractor

类似于 Shape Context distance,Hausdorff distance 基于 cv::ShapeDistanceExtractor 接口给出了另一种形状不相似度的度量。

Hausdorff distance 首先对于一张图像中的每个点找出另一幅图像上的最近点,而其中最大距离就是 Hausdorff distance。不过 Hausdorff distance 不是对称的(不过可以通过某些操作实现对称)。

,其中 

Hausdorff distance extractor 可以通过工厂方法 cv::createHausdorffDistanceExtractor() 产生。

cv::Ptr<cv::HausdorffDistanceExtractor> cv::createHausdorffDistanceExtractor( int distanceFlag = cv::NORM_L2, float rankProp = 0.6);

同时 cv::HausdorffDistanceExtractor 和 Shape  Context  distance  extractor 具有相同的接口,因此同样可以使用 cv::computeDistance() 计算对比目标的距离。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。