opencv實現(xiàn)輪廓高斯濾波平滑
本文實例為大家分享了opencv實現(xiàn)輪廓高斯濾波平滑的具體代碼,供大家參考,具體內(nèi)容如下
一個小測試的題目:
在圖像上點選,找到與點選處相鄰的顏色相近的點集合,對該點集合提取輪廓,對該點集合輪廓平滑處理,顯示處理結(jié)果。
#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);
//統(tǒng)計所有非零像素
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;
//獲取輪廓不包括輪廓內(nèi)的輪廓
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);//顯示圖像
}

漫水填充找到的輪廓

輪廓濾波平滑
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語言for循環(huán)嵌套for循環(huán)在實踐題目中應(yīng)用詳解
初學(xué)C語言,常常遇到for循環(huán)中嵌套個for循環(huán),初學(xué)者對于這種形式總是一知半解,這次我就整理了常見的for循環(huán)嵌套for循環(huán)的題目,我們一起爭取一舉拿下這類題。學(xué)廢他們,以后再見到就不怕啦!每天都要學(xué)一點呀。加油,奮斗的我們2022-05-05
C++中CopyFile和MoveFile函數(shù)使用區(qū)別的示例分析
這篇文章主要介紹了C++中CopyFile和MoveFile函數(shù)使用區(qū)別的示例分析,CopyFile表示將文件A拷貝到B,如果B已經(jīng)存在則覆蓋,MoveFile表示將文件A移動到。對此感興趣的可以來了解一下2020-07-07
詳解C++中StringBuilder類的實現(xiàn)及其性能優(yōu)化
在Java和C#中,StringBuilder可以創(chuàng)造可變字符序列來動態(tài)地擴(kuò)充字符串,那么在C++中我們同樣也可以實現(xiàn)一個StringBuilder并且用來提升性能,下面就來詳解C++中StringBuilder類的實現(xiàn)及其性能優(yōu)化2016-05-05
C語言判斷數(shù)是否為素數(shù)與素數(shù)輸出
大家好,本篇文章主要講的是C語言判斷數(shù)是否為素數(shù)與素數(shù)輸出,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽2021-12-12
求32位機(jī)器上unsigned int的最大值及int的最大值的解決方法
本篇文章是對求32位機(jī)器上unsigned int的最大值及int的最大值的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05

