学习|OpenCV匹配相似轮廓

学更好的别人,

做更好的自己。

——《微卡智享》

本文长度为2816,预计阅读9分钟

OpenCV匹配轮廓

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

实现效果

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

综合练习知识点

#实现的方式及用到的学习函数
1通过点击鼠标来选中需要匹配的轮廓,所以用到了setMouseCallback函数
2基本图像操作,灰度图,高斯模糊,形态学梯度操作
3查找轮廓findContours,获取鼠标点击的轮廓pointPolygonTest
4
轮廓匹配matchShapes

代码实现

微卡智享

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

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

main.cpp

#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

#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

#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那一张。

扫描二维码

获取更多精彩

微卡智享

「 往期文章 」

实践|OpenCV4.2使用DNN进行人脸检测二(视频篇)

实践|OpenCV4.2使用DNN进行人脸检测一(图片篇)

学习|Android中JetPack中的几个组件简单使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Vaccae

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

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

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

打赏作者

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

抵扣说明:

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

余额充值