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

Поиск координат объекта (пикселя)

Recommended Posts

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

#include "stdafx.h"
#include "stdio.h"
#include "cv.h"
#include "highgui.h"
#include "stdlib.h"
#include "math.h"

#ifndef min
#define min(a,b)            (((a) < (b)) ? (a) : (b))
#endif

int main(int argc, char* argv[])
{
        IplImage *img1=0, *img2=0, *diff=0, *sub=0, *strela=0, *crugi=0, *crugi1=0, *crugi2=0, *gray=0, *bin=0, *dst=0;

        // дефолтные названия картинок для обработки
        char file1[] = "Image0.jpg";
        char file2[] = "Image1.jpg";

        // имя картинки задаётся первым параметром
        char* filename1 = argc >= 2 ? argv[1] : file1;
        // получаем картинку
        img1 = cvLoadImage(filename1);
        printf("[i] first image: %s\n", filename1);

        // имя картинки задаётся первым параметром
        char* filename2 = argc >= 3 ? argv[2] : file2;
        // получаем картинку
        img2 = cvLoadImage(filename2);
        printf("[i] second image: %s\n", filename2);

      //Создаём однокональное изображение
       crugi = cvCreateImage( cvGetSize(img1), IPL_DEPTH_8U, 1 );
        // получаем границы
        cvCanny(img1, crugi, 200, 220, 3);
      cvShowImage("crugi",crugi);



   

      // покажем первоначальные изображения
     //   cvNamedWindow( "image1");
     //   cvShowImage( "image1", img1 );
     //   cvNamedWindow( "image2");
     //   cvShowImage( "image2", img2 );

      //Разница изображений
        // создаём картинку для хранения разницы
        diff = cvCloneImage(img1);
        sub = cvCloneImage(img1);
      cvZero(diff);

        // пробегаемся по всем пикселям изображения
        for( int y=0; y<diff->height; y++ ) {
                uchar* ptr1 = (uchar*) (img1->imageData + y * img1->widthStep);
                uchar* ptr2 = (uchar*) (img2->imageData + y * img2->widthStep);
                uchar* ptr = (uchar*) (diff->imageData + y * diff->widthStep);
                for( int x=0; x<diff->width; x++ ) {
                        // 3 канала:
                        // B
                        ptr[3*x] = ptr1[3*x] + ptr2[3*x] - 2 * min(ptr1[3*x], ptr2[3*x]);
                        // G
                        ptr[3*x+1] = ptr1[3*x+1] + ptr2[3*x+1] - 2 * min(ptr1[3*x+1], ptr2[3*x+1]);
                        // R
                        ptr[3*x+2] = ptr1[3*x+2] + ptr2[3*x+2] - 2 * min(ptr1[3*x+2], ptr2[3*x+2]);
                }
        }

        // вычитаем 
        cvSub(img1, img2, sub); 
      strela = cvCreateImage( cvGetSize(img1), IPL_DEPTH_8U, 1 );
      
      
      
      
       
       // выводим результат вычитания
        cvNamedWindow( "diff");
        cvShowImage( "diff", diff );
      //  cvNamedWindow( "sub");
      //  cvShowImage( "sub", sub );

      // Находим границы вычтенного изображения
      cvCanny(diff, strela, 300, 320, 3);
      cvNamedWindow( "strela");
        cvShowImage( "strela", strela );



        CvMemStorage* storage = cvCreateMemStorage(0);
        CvSeq* contours=0;

        // находим контуры
   cvFindContours( strela, storage,&contours,sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));

         //нарисуем контуры
        for(CvSeq* seq0 = contours;seq0!=0;seq0 = seq0->h_next){
                cvDrawContours(dst, seq0, CV_RGB(255,216,0), CV_RGB(0,0,250), 0, 1, 8); // рисуем контур
        }

        // ждём нажатия клавиши
        cvWaitKey(0);

        // освобождаем ресурсы
        cvReleaseImage(&img1);
        cvReleaseImage(&img2);
        cvReleaseImage(&diff);
        cvReleaseImage(&sub);

        // удаляем окна
        cvDestroyAllWindows();
        return 0;
}

file.php?id=328file.php?id=327

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Просканировать все изображение снизу вверх и найти первый белый пиксель.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

А не могли бы подсказать код, как это делать. Логически понимаю, а в перевод на с++ увы не знаю....Заранее благодарен

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Вот тут с пояснениями есть:

http://docs.opencv.org/2.4/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html

Только переходите на новый интерфейс С++ (где изображения в матрицах Mat ), старый (сишный IplImage* ) скоро отменят.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
		// пробегаемся по всем пикселям изображения
        for( int y=0; y<strela->height; y++ ) {
                int nChan = strela->nChannels;  // Определить количество каналов
               uchar* ptr = (uchar*) (strela->imageData + y * strela->widthStep);  
// widthStep - расстояние между соседними по вертикали точками изображения (число байт в одной строчке картинки). 
// Хотя это, скорее всего, число элементов (uchar) в одной строке массива данных. 
// Соответственно, для данного случая (при image->imageData == начало массива данных) по арифметике указателей
// ptr будет указывать на начало каждой строки массива данных картинки

                for( int x=0; x<strela->width; x++ ) {
                         // количество каналов вложили в nChan
                         // пробегаемся по всем каналам каждого пикселя
                         // конкретно здесь устанавливаются значения каналов каждого пикселя :)
                        ptr[nChan*x] = 255;     // B - синий
                        ptr[nChan*x+1] = 255;   // G - зелёный
                        ptr[nChan*x+2] = 255; // R - красный
				}
               
        }

Нашел вот такой способ обхода изображения. Не знаю как вывести координату, когда встречается белый пиксель. И как завершить обход когда первый белый пиксель найден. Подскажите пожалуйста уважаемые профессионалы с++.

На Mat пока не перехожу, так как не смог найти толком вещей которые мне необходимы (и увы в с++ пока ещё новичок).

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Для начала надо узнать сколько каналов  в изображении, которое Вы получаете после вычитания фона.

Если три, то код почти подходит (для одноканального код неверен). 

значения красного, синего и зеленого для точки (x,y) будут храниться в  

ptr[nChan*x], ptr[nChan*x+1] и  ptr[nChan*x+2].

У черного цвета, значения эти будут нулевые, у белого 255.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

А как вывести сами координаты этой точки (значение х и у) у которой ptr[nChan*x]=255, ptr[nChan*x+1]=255 и  ptr[nChan*x+2]=255?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Если трехканальное, то

if (ptr[nChan*x] == 255 && ptr[nChan*x + 1] == 255 && ptr[nChan*x + 2] == 255) {

 // например

cout << "Pixel is: " << x << " " << y << "\n";

}

Или вы куда хотите вывести?

Чтобы после первого найденного, больше не считало, сделайте условие для break

Изменено пользователем kilop

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Спасибо вывел все координаты белых пикселей. break в моем контексте не подходит, нужно искать минимальное значение x. Я так понимаю необходимо записывать данные в массив и искать минимальное значение. А возможно ли сразу вывести одно минимальное значение x и соответствующий ему y?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×