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
投稿
猜你喜欢
- flutter material widget组件之信息展示组件,供大家参考,具体内容如下widget分为两类:widgets librar
- 一直使用Eclipse环境开发Android,也尝鲜使用过Android Studio去开发,各种IDE配合Android SDK及SDK原
- 序言在flutter开发中,我们使用 bloc 框架,基于状态变更进行响应式开发。本篇文章,小轰将 bloc 核心业务块进行拆解简化,聊一聊
- JSON.toJSONString()空字段不忽略修改使用JSON.toJSONString(object)方法,返回的json中,默认会将
- 本章将具体讲解下拉菜单的交互。使用下拉菜单(Dropdown)插件,您可以向任何组件(比如导航栏、标签页、胶囊式导航菜单、按钮等)添加下拉菜
- 先看看效果Like This↓一、公共WiFi 公用电脑什么的在我们日常在线上工作、玩耍时,不论开电脑、登录淘宝、玩网游统统都会用到键盘输入
- 之前我们在使用vue进行 h5 表单录入的过程中,遇到了Android软键盘弹出,覆盖 h5页面 输入框 问题,在此进行回顾并分享给大家:系
- 本文实例为大家分享了android实现简易计算器展示的具体代码,供大家参考,具体内容如下效果图:一、如图,首先布局计算器主页显示activi
- activity A和BA 获取数据的activity B返回数据的activity点击A上的按钮,在A的textview上显示
- 本文实例讲述了C++实现的O(n)复杂度内查找第K大数算法。分享给大家供大家参考,具体如下:题目:是在一组数组(数组元素为整数,可正可负可为
- C++11 引入一个全新的线程库,包含启动和管理线程的工具,提供了同步(互斥、锁和原子变量)的方法,我将试图为你介绍这个全新的线
- 如图所示的效果相信大家都不陌生,我们可以使用很多种方法去实现此效果,这里自己采用CountDownTimer定时器简单封装下此效果,方便我们
- 构造方法以及参数:PageView可用于Widget的整屏滑动切换,如当代常用的短视频APP中的上下滑动切换的功能,也可用于横向页面的切换,
- 这里使用的是dynamic-datasource-spring-boot-starter ,它是一个基于springboot的快速集成多数据
- 一、整体设计1、需求分析池化技术是计算机中的一种设计模式,内存池是常见的池化技术之一,它能够有效的提高内存的申请和释放效率以及内存碎片等问题
- 先上图下拉刷新跟原生开发一样,下拉刷新在flutter里提供的有组件实现 RefreshIndicator一直不明白为啥组件中都提供下拉刷新
- SharedPreferences是Android中最容易理解的数据存储技术,实际上SharedPreferences处理的就是一个key-
- 最近研究了一下如何在Android上实现CoverFlow效果的控件,其实早在2010年,就有Neil Davies开发并开源出了这个控件,
- java 进制转换实例详解十进制转成十六进制:  
- 上篇介绍了几种图表的公共组件X、Y轴、背景Board的绘制。这章节介绍柱状图表的绘制,相对其它图表而言简单一些,这里主要介绍图表主体的绘制,