Перейти к содержимому
Compvision.ru

Halloween

Пользователи
  • Количество публикаций

    24
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные пользователем Halloween


  1. связность какая должна быть? 4-х или 8-ми?

    если например устранять разрывы просто соединением конечных точек, то будет не точно наверно, но вполне рабоче, но может можно как то более сложно интерполировать, поэтому я предлагал почитать про сплайны.

    наверно можно как то пройтись по точкам и смотреть их связность и помечать/удалять лишние, но например какие лучше удалять внутри контура или снаружи, или без разницы?

    + алгоритмы не учитывают маленькие циклы.(если они появятся)

    Желательно 8-ми связные.

    Насчет соединения конечных точек,то я сейчас работаю над этим,используя фильтр Калмана(фильтр прогнозирует след. положение точки по траектории).Это должно помочь сгладить места соединений.

    Без разницы откуда удалять,лишь бы не получилось лишних разрывов и процесс был автоматизирован.Свою идею как это сделать я представил выше(методом дифференцирования).


  2. Посмотри довольно тупую мою реализацию для твоего изображения:

    #include <list>
    
    #include <limits>
    
    
    #include <highgui.h>
    
    #include <cv.h>
    
    ////////////////////////////////////////////////////////////////////////////
    
    
    int main()
    
    {
    
    	IplImage* img = cvLoadImage("f:\\test.bmp", 0);
    
    
    	IplImage* img2 = cvCloneImage(img);
    
    
    	cvShowImage("original", img2);
    
    
    	// Немного доработаем исходное изображение для удобного писка контуров
    
    	cvSubRS(img, cvScalar(255), img);
    
    	cvDilate(img, img, 0, 1);
    
    	cvErode(img, img, 0, 1);
    
    
    	cvShowImage("img", img);
    
    
    	// Ищем контуры
    
    	CvMemStorage *storage = cvCreateMemStorage(0);
    
    	CvContourScanner traverse = cvStartFindContours(img, storage, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
    
    
    	// Контейнер для концевых точек
    
    	std::list<CvPoint> points;
    
    
    	size_t ccounter = 0;
    
    	for (CvSeq* contour = cvFindNextContour(traverse); contour; contour = cvFindNextContour(traverse))
    
    	{
    
    		// Совершено тупой и нерациональный поиск концевых точек
    
    		size_t min1 = std::numeric_limits<size_t>::max();
    
    		size_t min2 = std::numeric_limits<size_t>::max();
    
    		CvPoint min_p1 = cvPoint(0, 0);
    
    		CvPoint min_p2 = cvPoint(500, 500);
    
    
    		for (int i = 0; i < contour->total; ++i)
    
    		{
    
    			CvPoint p1 = *(CvPoint*)cvGetSeqElem(contour, i);
    
    
    			size_t near_count = 0;
    
    			for (int j = 0; j < contour->total; ++j)
    
    			{
    
    				if (i != j)
    
    				{
    
    					CvPoint p2 = *(CvPoint*)cvGetSeqElem(contour, j);
    
    					if (abs(p1.x - p2.x) < 5 && abs(p1.y - p2.y) < 5)
    
    						++near_count;
    
    				}
    
    			}
    
    
    			if ((near_count < min1) && (abs(p1.x - min_p2.x) > 10 || abs(p1.y - min_p2.y) > 10))
    
    			{
    
    				min1 = near_count;
    
    				min_p1 = p1;
    
    			}
    
    			else if ((near_count < min2) && (abs(min_p1.x - p1.x) > 10 || abs(min_p1.y - p1.y) > 10))
    
    			{
    
    				min2 = near_count;
    
    				min_p2 = p1;
    
    			}
    
    		}
    
    
    		points.push_back(min_p1);
    
    		points.push_back(min_p2);
    
    
    		printf("%u\n", ++ccounter);
    
    	}
    
    
    	cvEndFindContours(&traverse);
    
    	cvReleaseMemStorage(&storage);
    
    
    	// Соединяем ближайшие концевые точки прямыми
    
    	for (std::list<CvPoint>::iterator it1 = points.begin(); it1 != points.end(); it1 = points.erase(it1))
    
    	{
    
    		double min_dist = std::numeric_limits<double>::max();
    
    
    		std::list<CvPoint>::iterator it2 = it1;
    
    		std::list<CvPoint>::iterator best_it = it1;
    
    		++best_it;
    
    		for (++it2; it2 != points.end(); ++it2)
    
    		{
    
    			double dist = sqrt((double)((it1->x - it2->x) * (it1->x - it2->x) + (it1->y - it2->y) * (it1->y - it2->y)));
    
    			if (dist < min_dist)
    
    			{
    
    				min_dist = dist;
    
    				best_it = it2;
    
    			}
    
    		}
    
    
    		cvLine(img2, *it1, *best_it, cvScalar(0));
    
    		points.erase(best_it);
    
    	}
    
    
    	cvShowImage("result", img2);
    
    
    	cvWaitKey();
    
    
    	cvReleaseImage(&img2);
    
    	cvReleaseImage(&img);
    
    	cvDestroyAllWindows();
    
    
    	return 0;
    
    }
    
    ////////////////////////////////////////////////////////////////////////////

    Сравни картинки original и result. Это то, что тебе надо?

    Практически то,но маленькие разрывы всё-равно остались.Посмотрите как я реализовал свою задачу,воспользовавшись тем,что вы предложили ранее:

    dist.cpp

    Решение действенно,но для него нужно давать четкое изображение без шумов и утолщений,иначе будут баги.

    Есть идея почистить изображение с помощью дифференцирования.Поясню алгоритм:

    1.Двигаться по горизонтали,пока не найдется точка.

    2.Если точка нашлась-двигаться при координате Х этой точки только уже по-вертикали(по Y):

    -если точка не нашлась-оставляем найденную и двигаемся дальше;

    -если нашлась,то накладываем точку ,найденную по-вертикали на точку,найденную по-горизонтали(логическое ИЛИ).Таким образом получаем нужную нам точку,а остальные отбрасываем.

    3.Двигаемся дальше.

    Алгоритм вроде оптимальный,но никак не дойду мыслями,как его красиво реализовать в VS.


  3. вам скорее нужна не просто однопикселезация, а чтобы кривая была гладкая и неразрывная. (в математической правильности фурмулировки не уверен :))

    я думаю только морфологией тут не обойтись. думаю тут надо присмотрется к сплайнам.

    http://www.gamedev.ru/code/forum/?id=124256

    Мне скорее надо убрать лишние помехи (шумы) с линий!Просто если я сделаю кривую гладкой,то я не решу свою задачу ,потому что будут большие потери.А разрывность я устраняю другим методом.


  4. Воспользовался следующей морфологией,но потери слишком большие,как их можно уменьшить:

    
    //cvDilate()
    
    
    #include "stdafx.h"
    
    
    #include <cv.h>
    
    #include <highgui.h>
    
    #include <stdlib.h>
    
    #include <stdio.h>
    
    
    #define  CV_SHAPE_ELLIPSE   1
    
    
    IplImage* image = 0;
    
    IplImage* dst = 0;
    
    
    IplImage* dilate = 0;
    
    
    int radius = 1;
    
    int radius_max=10;
    
    
    //
    
    // функция-обработчик ползунка - 
    
    // радиус ядра
    
    void myTrackbarRadius(int pos) {
    
            radius = pos;
    
    }
    
    
    int iterations = 1;
    
    int iterations_max = 10;
    
    
    //
    
    // функция-обработчик ползунка - 
    
    // число итераций
    
    void myTrackbarIterations(int pos) {
    
            radius = pos;
    
    }
    
    
    int main(int argc, char* argv[])
    
    {
    
    
    	 IplImage* image = cvLoadImage("d:\\test.bmp", 1);
    
                // клонируем картинку 
    
             dst = cvCloneImage(image);
    
             dilate = cvCloneImage(image);
    
    
             // окно для отображения картинки
    
            cvNamedWindow("original",CV_WINDOW_AUTOSIZE);
    
            cvNamedWindow("dilate",CV_WINDOW_AUTOSIZE);
    
    
            cvCreateTrackbar("Radius", "original", &radius, radius_max, myTrackbarRadius);
    
            cvCreateTrackbar("Iterations", "original", &iterations, iterations_max, myTrackbarIterations);
    
    
    
            while(1){
    
    
                    // показываем картинку
    
                    cvShowImage("original",image);
    
    
                    // создаём ядро
    
                    IplConvKernel* Kern = cvCreateStructuringElementEx(radius+1, radius+1, radius, radius,  CV_SHAPE_ELLIPSE);
    
    
                    // выполняем преобразования
    
    
                    cvDilate(image, dilate, Kern, iterations);
    
    
                    // показываем результат
    
    
                    cvShowImage("dilate",dilate);
    
    
    				//cvSaveImage("dilate.jpg", dilate);
    
    
                    cvReleaseStructuringElement(&Kern);
    
    
                    char c = cvWaitKey(33);
    
                    if (c == 27) { // если нажата ESC - выходим
    
    		                       cvSaveImage("dilate.jpg", dilate);  
    
    					break;
    
                    }
    
            }
    
    
            // освобождаем ресурсы
    
            cvReleaseImage(&image);
    
            cvReleaseImage(&dst);
    
            cvReleaseImage(&dilate);
    
            // удаляем окно
    
            cvDestroyWindow("original");
    
            cvDestroyWindow("dilate");
    
            return 0;
    
    }
    
    

    Пробовал на изображении:

    test.bmp

    потери большие...


  5. Есть монохромное изображение с линиями,но линии нечёткие.Пытаюсь однопикселизировать изображение так,чтобы потери были минимальные и остался только контур.

    Например,изображение:

    test.bmp

    Нужно убрать нечеткости такого рода:

    3.bmp

    dilate.bmp

    Кто сталкивался с подобной проблемой,буду рад за информацию.


  6. Целесообразно будет использовать функцию с подальшей передачей параметров ?И куда лучше сохранять подошедшие концы.Я немного сбился со своего алгоритма.

    
    //Евклидово расстояние
    
    double dist(const CvPoint &w1, const CvPoint &w2)
    
    {
    
    return  sqrt((double)((w2.x - w1.x)*(w2.x - w1.x) +(w2.y - w1.y)*(w2.y - w1.y))) ;
    
    }
    
    

    Или можно сделать все как-то проще?


  7. Я разобрался,все работает,проблема была в версии OpenCV.

    Я для начала хочу все-таки восстановить элементарное изображение,используя фильтр Калмана,думаю,как правильней будет найти соответствующие концы.

    А насчет оптимизации,я думаю ,что все-таки целесообразней будет выполнять восстановление в заданном окне,которое будет перемещаться по изображению,главное правильно размер подобрать.


  8. Чувствую,что тоже на нее перейду,потому что Builder ругается на it1,пишет,что он уже был декларирован.Может я где-то что-то и недоглядел :

    
      for (tracks_cont::iterator it1 = tracks.begin(); it1 != tracks.end()
    
            {
    
                    if (it1->size() == 1)
    
                            it1 = tracks.erase(it1);
    
                    else
    
                            ++it1;
    
            }
    
           for (tracks_cont::iterator it1=tracks.begin(); it1 != tracks.end(); ++it1)
    
            {
    
                    for (points_cont::iterator it2 = it1->begin(); it2 != it1->end(); ++it2)
    
                    {
    
                            (second_img->imageData + it2->y * second_img->widthStep + it2->x)[0] = 0;
    
    
                            cvShowImage("second_img", second_img);
    
                            if (cvWaitKey(40) > 0)
    
                                    break;
    
                    }
    
            }
    
    
    [/code]

    Сейчас буду пробовать в студии.


  9. На данном этапе я пока собрал нужную литературу и додумываю как всё-таки использовать фильтр Калмана,ведь он в основном используется для динамических систем.

    Я так понял ,что нужно создать окно,которое будет проходить по изображению и в котором будет проводиться наше восстановление.У меня была идея сделать из линии что-то вроде траектории движения и на разрыве использовать фильтр Калмана до тех пор,пока траектория не продолжится .Но твоё решение вроде смотрится проще,только я пока не сильно понимаю как найти конец какой цепочки подходит к концу другой.Если есть примеры или литература-буду благодарен за просвещение!


  10. Есть только изображение,в этом-то и загвоздка!Я так понимаю,что массив с координатами точек надо получить в ходе выполнения задачи.

    Мне бы хотя бы разобраться как одну линию соединить,дальше уже буду сам додумывать!


  11. Есть изображение с разорванной линией!

    Как можно восстановить его в Builder 6,используя фильтр Калмана,который хорошо описан в OpenCV.Пример изображения представлен на рисунке.

    Фильтр Калмана прогнозирует следующее положение объекта,в нашем случае линии.

    post-1323-0-40442200-1299252316_thumb.jp

    Кто сталкивался или знает как решить эту проблему,видел похожие исходники помогите!

×