前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >学习|OpenCV匹配相似轮廓

学习|OpenCV匹配相似轮廓

作者头像
Vaccae
发布2020-04-10 16:12:21
2.2K0
发布2020-04-10 16:12:21
举报
文章被收录于专栏:微卡智享微卡智享

其实查找相似的东西用机器学习训练的方式处理应该是最好的,今天做的这个小练习主要是针对OpenCV的matchShapes函数的练习,正好把OpenCV的几个函数综合运用一下。

实现效果

从图上我们可以看出来,通过鼠标点击找到我们要实现的轮廓,然后通过匹配轮廓把找到的轮廓在左边的图中都画出来,其中是我们点击的轮廓就红色填充,匹配的相似轮廓用的蓝色填充,就是实现的一个这样简单的效果。

综合练习知识点

#

实现的方式及用到的学习函数

1

通过点击鼠标来选中需要匹配的轮廓,所以用到了setMouseCallback函数

2

基本图像操作,灰度图,高斯模糊,形态学梯度操作

3

查找轮廓findContours,获取鼠标点击的轮廓pointPolygonTest

4

轮廓匹配matchShapes

代码实现

微卡智享

OpenCV的项目搭建及配置请直接看《VS2017配置OpenCV通用属性

整个项目中,一个main.cpp的文件,一个matchShape的类,如下图:

main.cpp

代码语言:javascript
复制
#include<opencv2/opencv.hpp>
#include<iostream>
#include"matchShape.h"

using namespace cv;
using namespace std;

string showsrc = "源图";
Point mPoint;
Mat src, srccopy;
void onMouse(int event, int x, int y, int flags, void* ustc); //鼠标回调函数

int main(int agrc, char** argv) {

  src = imread("E:/DCIM/tempsrc.jpg");
  namedWindow(showsrc);
  //设置鼠标响影事件
  setMouseCallback(showsrc, onMouse);

  imshow(showsrc, src);

  waitKey(0);
  return 0;
}

void onMouse(int event, int x, int y, int flags, void* ustc)
{
  //鼠标左键按下抬起
  if (event == EVENT_LBUTTONUP)
  {
    mPoint = Point(x, y);
    srccopy = src.clone();
    matchShape shape = matchShape();
    srccopy = shape.findmatchShape(srccopy, mPoint);
    imshow("res", srccopy);
  }
}

matchShape.h

代码语言:javascript
复制
#pragma once
#include <opencv2/opencv.hpp>
#include<iostream>

using namespace cv;
using namespace std;
class matchShape
{
private: 
  //匹配阈值
  double threshdouble = 0.3;
  //获取图像轮廓
  vector<vector<Point>> getContours(Mat src);
  //获取点击的点的所在轮廓
  vector<Point> getPointContour(vector<vector<Point>> contours, Point pt);
public:
  Mat findmatchShape(Mat src, Point pt);
};

matchShape.cpp

代码语言:javascript
复制
#include "matchShape.h"

vector<vector<Point>> matchShape::getContours(Mat src)
{
  vector<vector<Point>> contours;
  Mat gray,tmp;
  //1.灰度图
  cvtColor(src, gray, COLOR_BGR2GRAY);
  //2.高斯模糊
  GaussianBlur(gray, gray, Size(3, 3), 0.5, 0.5);
  //3.二值化
  threshold(gray, gray, 0, 255, THRESH_BINARY | THRESH_OTSU);
  //4.形态学梯度处理
  Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
  morphologyEx(gray, gray, MORPH_GRADIENT, kernel);
  //imshow("gray", gray);

  //4.查找轮廓
  findContours(gray, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

  return contours;
}

//获取点所在的轮廓
vector<Point> matchShape::getPointContour(vector<vector<Point>> contours, Point pt)
{
  for (int i = 0; i < contours.size(); i++) {
    if (pointPolygonTest(contours[i], pt, false) >= 0) return contours[i];
  }
  return vector<Point>();
}

Mat matchShape::findmatchShape(Mat src, Point pt)
{
  Mat dst = Mat::zeros(src.size(), CV_8UC3);
  //获取轮廓
  vector<vector<Point>> contours = getContours(src);

  //获取点所在的轮廓
  vector<Point> ptcontour = getPointContour(contours, pt);

  if (ptcontour.size() <= 0) return dst;

  //获取相似轮廓
  for (int t = 0; t < contours.size(); t++) {
    double ret = matchShapes(ptcontour, contours[t], CONTOURS_MATCH_I3, 0.0);
    cout << t << "相似度:" << ret << endl;
    if (ret == 0) drawContours(dst, contours, t, Scalar(0, 0, 255),-1);
    else if (ret <= threshdouble) 
      drawContours(dst, contours, t, Scalar(255, 0, 0),-1);
  }

  return dst;
}

运行起来后通过点击鼠标就可以直接显示出来了。

测试的图像在OpenCV的源码sources/samples/data下,我用的是smarties.png那一张。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-04-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 微卡智享 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • main.cpp
  • matchShape.h
  • matchShape.cpp
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档