opencv实现轮廓高斯滤波平滑
作者:BHY_ 发布时间:2023-07-23 02:05:56
标签:opencv,轮廓,高斯滤波
本文实例为大家分享了opencv实现轮廓高斯滤波平滑的具体代码,供大家参考,具体内容如下
一个小测试的题目:
在图像上点选,找到与点选处相邻的颜色相近的点集合,对该点集合提取轮廓,对该点集合轮廓平滑处理,显示处理结果。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
//************************************
// Method: findRegion 漫水填充
// FullName: findRegion
// Access: public
// Returns: vector<Point>
// Qualifier:
// Parameter: Mat img
// Parameter: Point pos
// Parameter: int LowDifference
// Parameter: int UpDifference
//************************************
vector<Point> findRegion(Mat img, Point pos, int LowDifference, int UpDifference)
{
Mat image = img.clone();
Mat imgBack = img.clone();
Rect ccomp;
Scalar pixel = image.at<Vec3b>(pos);
Scalar pixel2 = Scalar(255 - pixel[0], 255 - pixel[1], 255 - pixel[2], pixel[3]);
floodFill(image, pos, pixel2, &ccomp, Scalar(LowDifference, LowDifference, LowDifference),
Scalar(UpDifference, UpDifference, UpDifference));
Mat diff;
absdiff(image, imgBack, diff);
//统计所有非零像素
vector<Point> pt;
for (int i = 0; i < diff.rows; i++)
{
for (int j = 0; j < diff.cols; j++)
{
Point newPos(j, i);
Scalar pixel3 = diff.at<Vec3b>(newPos);
if (pixel3[0] != 0 || pixel3[1] != 0 || pixel3[2] != 0)
{
pt.push_back(newPos);
}
}
}
return pt;
}
//************************************
// Method: findPerimeter 从点集合中寻找轮廓点
// FullName: findPerimeter
// Access: public
// Returns: vector<Point>
// Qualifier:
// Parameter: vector<Point> pt
// Parameter: Size size
//************************************
vector<Point> findPerimeter(vector<Point> pt, Size size)
{
Mat imgGray(size, CV_8UC1, Scalar(0));
for (int i = 0; i < pt.size(); i++)
{
imgGray.at<uchar>(pt[i]) = 255;
}
std::vector<std::vector<cv::Point>> contours;
//获取轮廓不包括轮廓内的轮廓
cv::findContours(imgGray.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
return contours[0];
}
//************************************
// Method: displayImage 显示图像
// FullName: displayImage
// Access: public
// Returns: void
// Qualifier:
// Parameter: Mat img
// Parameter: vector<Point> contours 轮廓点
// Parameter: Point pos
//************************************
void displayImage(Mat img, vector<Point> contours, Point pos)
{
Mat imgShow = img.clone();
for (int i = 0; i < contours.size(); i++)
{
imgShow.at<Vec3b>(contours[i])[0] = 0;
imgShow.at<Vec3b>(contours[i])[1] = 0;
imgShow.at<Vec3b>(contours[i])[2] = 0;
}
circle(imgShow, pos, 3, Scalar(0, 0, 0), 1, 8, 0);//画用户选择的点
imshow("img", imgShow);
waitKey(0);
}
//************************************
// Method: findSmoothPeimeter 高斯滤波轮廓点平滑
// FullName: findSmoothPeimeter
// Access: public
// Returns: void
// Qualifier:
// Parameter: Mat img 原图
// Parameter: vector<Point> pt 轮廓点集合
//************************************
void findSmoothPeimeter(Mat img, vector<Point> pt)
{
vector<Point> contours = findPerimeter(pt, img.size());
Mat im;
cvtColor(img, im, CV_BGR2GRAY);
Mat cont = ~im;
Mat original = Mat::zeros(im.rows, im.cols, CV_8UC3);
Mat smoothed = img.clone();
// contour smoothing parameters for gaussian filter
int filterRadius = 10;
int filterSize = 2 * filterRadius + 1;
double sigma = 10;
size_t len = contours.size() + 2 * filterRadius;
size_t idx = (contours.size() - filterRadius);
vector<float> x, y;
for (size_t i = 0; i < len; i++)
{
x.push_back(contours[(idx + i) % contours.size()].x);
y.push_back(contours[(idx + i) % contours.size()].y);
}
// filter 1-D signals
vector<float> xFilt, yFilt;
GaussianBlur(x, xFilt, Size(filterSize, filterSize), sigma, sigma);
GaussianBlur(y, yFilt, Size(filterSize, filterSize), sigma, sigma);
// build smoothed contour
vector<Point> smoothContours;
for (size_t i = filterRadius; i < contours.size() + filterRadius; i++)
{
smoothContours.push_back(Point(xFilt[i], yFilt[i]));
}
Scalar color;
for (int i = 0; i < smoothContours.size(); i++)
{
smoothed.at<Vec3b>(smoothContours[i])[0] = 0;
smoothed.at<Vec3b>(smoothContours[i])[1] = 0;
smoothed.at<Vec3b>(smoothContours[i])[2] = 0;
}
imshow("smoothed", smoothed);
waitKey(10);
}
void main()
{
Mat img = imread("4.jpg", 1);
vector<Point> pt, contours;
Point pos(1438, 590);//先列后行
int para1 = 2;
int para2 = 2;
pt = findRegion(img, pos, para1, para2);
findSmoothPeimeter(img, pt);
contours = findPerimeter(pt, img.size());//轮廓点集合
displayImage(img, contours, pos);//显示图像
}
漫水填充找到的轮廓
轮廓滤波平滑
来源:https://blog.csdn.net/qq_15947787/article/details/78518834
0
投稿
猜你喜欢
- 目录一、Lambda 表达式简介1、什么是 Lambda 表达式2、为什么需要 Lambda 表达式二、函数式接口和定义1、什么是函数式接口
- 问题怎么配置springBoot 内置tomcat,才能使得自己的服务效率更高呢?基础配置Spring Boot 能支持的最大并发量主要看其
- 获取当前年的周数 /// <summary> /// 获得今年有几周 /// </summa
- 本文实例为大家分享了自定义渐变式炫酷动画的ListView下拉刷新,供大家参考,具体内容如下主要要点listview刷新过程中主要有三个步骤
- GridView基础新建一个HelloGridView的工程修改main.xml代码如下:<?xml version="1.
- 一、需求来源app需要支持实现游客模式,启动后直接进入首页菜单,但是进入二级页则自动调用登录页面。总结需求就是父视图拦截子视图的响应事件,思
- Android 自定义标题栏的实例详解开发 Android APP 经常会用到自定义标题栏,而有多级页面的情况下还需要给自定义标
- 一、为什么会存在动态内存int data=20;//在栈空间上开辟4个字节空间char ch[5]={0};//在栈开辟5个字节连续空间上面
- Docker 是一种“轻量级”容器技术,它几乎动摇了传统虚拟化技术的地位,现在国内外已经有越来越多的公司开始逐步使用 Docker 来替换现
- 是否允许循环依赖和bean的命名重复取决于beanfactory的两大属性allowBeanDefinitionOverriding和all
- 本文研究的主要是java中的null“类型”的相关实例,具体介绍如下。先给出一道简单的null相关的题目,引发我们对null的探讨,后面会根
- 创建字符串常见的构造 String 的方式// 方式一String str = "Hello Bit";// 方式二St
- Java中代码的加载顺序所能了解的知识点类的依赖关系static代码块的加载时间继承类中构造器的隐式调用非static的成员变量初始化时间m
- 概述本文介绍通过java程序向PDF文档添加图片,以及替换和删除PDF中已有的图片。另外,关于图片的操作还可参考设置PDF 图片背景、设置P
- 目录闲言碎语:背景Actuator介绍Rest方法来查看Actuatorpom.xml引入Actuator依赖配置application.y
- 1.选择一个WebService接口作测试假设 WebService url 为 http://ws.webxml.com.cn/WebSe
- 本文记录了用自定义Camera实现的简单拍照功能。Camera类在5.0以后不推荐使用了,取而代之的是android.hardware.ca
- 一、APP端调用1、注册广播监听查找结果//蓝牙发现设备和查找结束广播IntentFilter intentFilter = new Int
- android仿照qq的顶部栏效果,主要就是利用fragment manager把fragment设置显示内容(1)在activity_ma
- 需求基于MTK8163 8.1平台定制导航栏部分,在左边增加音量减,右边增加音量加思路需求开始做之前,一定要研读SystemUI Navig