OpenCV найти вогнутый корпус
У меня есть набор дискретных точек, показанных на изображении, например:
Я хочу восстановить или увеличить выборку (я не уверен, как правильно ее описать) изображение, чтобы полученное изображение было следующим, Оно не обязательно должно быть точно таким же, как пример изображения, но основная идея - заполнить оригинал.
У меня есть первоначальное представление о том, как это сделать. Но я не знаю, как это сделать после первого шага. Моя идея состоит в том, чтобы сначала отделить изображение с помощью kmeans и выяснить различные объекты. И я успешно это сделал. Полученные изображения после kmeans:,
После kmeans я хочу использовать поиск контура или что-то вроде вогнутости, чтобы получить контур этих фигур и заполнить форму, используя такие функции, как заливка отверстий. Однако, я обнаружил, что "найти контур" не работает, он будет рассматривать каждый отдельный пиксель как контур.
Другой способ, которым я думаю, - использовать интерполяцию. Но я не уверен, возможно ли это с такими редкими точками. У кого-нибудь есть идеи о том, как это сделать? Я не уверен, что я на правильном пути, и я открыт для любых решений.
Большое спасибо!
1 ответ
Взгляните на морфологические преобразования. Я бы начал с операции расширения с использованием большого ядра, скажем, MORPH_ELLIPSE с размером (15,15). После этого разбавьте капли обратно, используя операцию эрозии с ядром того же размера. Посмотрите на документы здесь. Обратите внимание, что OpenCV также предлагает цепочечные или последовательные морфологические операции. Смотрите здесь. Затем вы увидите, что мое предложение является "закрывающей" операцией.
Обновление: я экспериментировал с простым расширением и контуром, чтобы получить результаты, показанные на изображении. Результаты, кажется, удовлетворяют общим требованиям проблемы.
Аналогичным образом, что означает "реальное время" для приложения, не указано, но этот набор операций может быть быстро выполнен и может быть легко применен к приложению со скоростью 30 кадров в секунду.
Фрагмент кода ниже:
// Convert image to grayscale
cvtColor(src, gray, CV_BGR2GRAY);
threshold(gray, gray, 128.0, 128.0, THRESH_BINARY);
// Dilate to fill holes
dilate(gray, dest, getStructuringElement(MORPH_ELLIPSE, Size(13,13)));
// Find contours
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(dest, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0,0));
// Prune contours
float maxArea = 0.0f;
for (size_t i = 0; i< contours.size(); i++)
{
if (contourArea(contours[i]) >= maxArea)
{
maxArea = contourArea(contours[i]);
}
}
float minArea = 0.20f * maxArea;
vector<vector<Point> > prunedContours;
for (size_t i = 0; i< contours.size(); i++)
{
if (contourArea(contours[i]) >= minArea)
{
prunedContours.push_back(contours[i]);
}
}
// Smooth the contours
vector<vector<Point> > smoothedContours;
smoothedContours.resize(prunedContours.size());
for (size_t i=0;i<prunedContours.size();i++)
{
vector<float> x;
vector<float> y;
const size_t n = prunedContours[i].size();
for (size_t j=0;j<n;j++)
{
x.push_back(prunedContours[i][j].x);
y.push_back(prunedContours[i][j].y);
}
Mat G;
transpose(getGaussianKernel(11,4.0,CV_32FC1),G);
vector<float> xSmooth;
vector<float> ySmooth;
filter2D(x,xSmooth, CV_32FC1, G);
filter2D(y,ySmooth, CV_32FC1, G);
for (size_t j=0;j<n;j++)
{
smoothedContours[i].push_back(Point2f(xSmooth[j],ySmooth[j]));
}
}