1. OpenCV шаг за шагом. Введение.
2. OpenCV шаг за шагом. Установка.
3. OpenCV шаг за шагом. Hello World.
4. OpenCV шаг за шагом. Загрузка картинки
Продолжим знакомство с OpenCV с простой загрузки картинки из файла.
Этот пример будет основой почти всех будущих программ 🙂
Кстати, чтобы немного развеселить изложение материала рассказ будет вестись от имени знаменитого Чеширского Кота
Думается, что его возможность исчезать будет просто незаменимой для компьютерного зрения 😉
Пррррррррррошу, уважаемый…
Итак, для самого что ни на есть Чеширского OpenCV, рассмотрим простой тестовый пример, который просто выводит картинку, имя которой передано в виде первого параметра программы (если параметров нет — будет пытаться открыть файл Image0.jpg).
Но параметр я разумеется передам и это будет самый Чеширский параметр, а именно моя фотография 🙂
#include <cv.h> #include <highgui.h> #include <stdlib.h> #include <stdio.h> IplImage* image = 0; IplImage* src = 0; int main(int argc, char* argv[]) { // имя картинки задаётся первым параметром char* filename = argc == 2 ? argv[1] : "Image0.jpg"; // получаем картинку image = cvLoadImage(filename,1); // клонируем картинку src = cvCloneImage(image); printf("[i] image: %s\n", filename); assert( src != 0 ); // окно для отображения картинки cvNamedWindow("original",CV_WINDOW_AUTOSIZE); // показываем картинку cvShowImage("original",image); // выводим в консоль информацию о картинке printf( "[i] channels: %d\n", image->nChannels ); printf( "[i] pixel depth: %d bits\n", image->depth ); printf( "[i] width: %d pixels\n", image->width ); printf( "[i] height: %d pixels\n", image->height ); printf( "[i] image size: %d bytes\n", image->imageSize ); printf( "[i] width step: %d bytes\n", image->widthStep ); // ждём нажатия клавиши cvWaitKey(0); // освобождаем ресурсы cvReleaseImage(& image); cvReleaseImage(&src); // удаляем окно cvDestroyWindow("original"); return 0; }
Результат работы от загрузки моей фотографии:
рассмотрим новые функции, которые использовались в данном примере:
IplImage* cvLoadImage( const char* filename, int iscolor=CV_LOAD_IMAGE_COLOR );
— загружает картинку из файла.
filename — имя файла
iscolor — определяет как представить картинку
iscolor > 0 — цветная картинка с 3-мя каналами
iscolor == 0 — картинка будет загружена в формате GRAYSCALE (градации серого)
iscolor < 0 - картинка будет загружена как есть:
/* 8bit, color or not */ #define CV_LOAD_IMAGE_UNCHANGED -1 /* 8bit, gray */ #define CV_LOAD_IMAGE_GRAYSCALE 0 /* ?, color */ #define CV_LOAD_IMAGE_COLOR 1 /* any depth, ? */ #define CV_LOAD_IMAGE_ANYDEPTH 2 /* ?, any color */ #define CV_LOAD_IMAGE_ANYCOLOR 4
функция поддерживает следующие форматы изображений:
- Windows bitmaps - BMP, DIB - JPEG files - JPEG, JPG, JPE - Portable Network Graphics - PNG - Portable image format - PBM, PGM, PPM - Sun rasters - SR, RAS - TIFF files - TIFF, TIF
IplImage* cvCloneImage( const IplImage* image );
— делает полную копию изображения image, включая заголовок, данные и ROI (Region Of Interest — регион интересов — интересующая область на рисунке).
Обе функции возвращают указатель на картинку IplImage.
Картинка, в OpenCV, представлена структурой вида:
// OpenCV2.0\include\opencv\cxtypes.h typedef struct _IplImage { int nSize; /* sizeof(IplImage) */ int ID; /* version (=0)*/ int nChannels; /* Most of OpenCV functions support 1,2,3 or 4 channels */ int alphaChannel; /* Ignored by OpenCV */ int depth; /* Pixel depth in bits: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F are supported. */ char colorModel[4]; /* Ignored by OpenCV */ char channelSeq[4]; /* ditto */ int dataOrder; /* 0 - interleaved color channels, 1 - separate color channels. cvCreateImage can only create interleaved images */ int origin; /* 0 - top-left origin, 1 - bottom-left origin (Windows bitmaps style). */ int align; /* Alignment of image rows (4 or 8). OpenCV ignores it and uses widthStep instead. */ int width; /* Image width in pixels. */ int height; /* Image height in pixels. */ struct _IplROI *roi; /* Image ROI. If NULL, the whole image is selected. */ struct _IplImage *maskROI; /* Must be NULL. */ void *imageId; /* " " */ struct _IplTileInfo *tileInfo; /* " " */ int imageSize; /* Image data size in bytes (==image->height*image->widthStep in case of interleaved data)*/ char *imageData; /* Pointer to aligned image data. */ int widthStep; /* Size of aligned image row in bytes. */ int BorderMode[4]; /* Ignored by OpenCV. */ int BorderConst[4]; /* Ditto. */ char *imageDataOrigin; /* Pointer to very origin of image data (not necessarily aligned) - needed for correct deallocation */ } IplImage;
т.о. вот какую информацию мы получаем в консоли:
image->nChannels // число каналов картинки (RGB, хотя в OpenCV - BGR ) (1-4) image->depth // глубина в битах image->width // ширина картинки в пикселях image->height // высота картинки в пикселях image->imageSize // память занимаемая картинкой (==image->height*image->widthStep) image->widthStep // расстояние между соседними по вертикали точками изображения (число байт в одной строчке картинки - может потребоваться для самостоятельного обхода всех пикселей изображения)
Пока на этом прервёмся, до встречи уважаемые!
Читать далее: 5. OpenCV шаг за шагом. Вывод видео
50 комментариев на «“4. OpenCV шаг за шагом. Загрузка картинки”»
У меня проблема с загрузкой файла. Почему-то не загружается картинка или видео. cvLoadImage(«pic_my.jpg», 1) возвращает FALSE. В результате получаю окно, залитое просто серым цветом, картинка не отображается. Тоже самое и с видео. Использую версию библиотеки 1.0. Win7. VS2008. В чем может быть дело?
странно. возможно не можен найти файл?
и почему старая версия? попробуйте поработать с OpenCV 2.1
Другая проблема: в filename вписываю изображение формата .tif
При этом ShowImage отображает серый экран (только окно), но не отображает картинку.
Как заставить opencv 2.1.0 открывать и работать с .tif?
у меня .tif-файлы открывает без проблем.
Если вы программируете в Visual Studio и запускаете программу не из директории, а прямо из-под IDE (через F5), то картинка должна лежать в директории проекта.
функция cvShowImage выдает ошибку при запуске программы F5, если filename = argc == 2? argv[1]: «d:/Program Files/fig.tif»;
видимо, cvShowImage не работает с tif
Кроме того, при задании типа TIFF* image = 0 и далее cvShowImage(«original»,image); выдает ошибку, что не может преобразовать TIFF в IplImage.
Может быть не хватает tif-библиотек или t-f.h или cpp файлов?
т.е. файлы другого формата у вас открываются?
если вы не в Linux-е, нужно писать:
Работаю в Windows XP, Visual Studio 2008. Текст программы в точности повторяет Ваш, я разместил картинку qwe.tif в папке проекта. Вместо image0.jpg написал qwe.TIF.
При запуске с F5 программа прерывается и в отдельном окне написано: Необработанное исключение в «0x7c812afb» в «01_openimage.exe»: Исключение Microsoft C++: cv::Exception по адресу 0x0011fcb4…
То же самое пишет, если бы я использовал картинку Image0.jpg, но ее бы не было в папке проекта.
Пожалуйста, помогите. Очень нужно настроить OpenCV 2.1.0 на открытие и работу с .TIF
Спасибо
только что проделал те же шаги 🙂
такое исключение вываливается, если не найдена картинка.
при запуске через F5 картинка должна лежать в папке, где и проектный файл с исходниками.
Или же проверьте проще — положите картинку в директорию к exe-ку и запустите exe-файл.
Код программы: #include «stdafx.h»
#include <cv.h>
#include <highgui.h>
#include <stdlib.h>
#include <stdio.h>
#include <tiffio.h>
IplImage* image = 0;
IplImage* image2 = 0;
IplImage* src = 0;
IplImage* src2 = 0;
TIFF* imgtiff = 0;
int main(int argc, char* argv[])
{
// имя картинки задаётся первым параметром
char* filename = argc == 2? argv[1]: «qwe.TIF»;
char* filename2 = argc == 2? argv[1]: «sf.jpg»;
// получаем картинку
image = cvLoadImage(filename,1);
image2 =cvLoadImage(filename2,1);
// окно для отображения картинки
cvNamedWindow(«original»,CV_WINDOW_AUTOSIZE);
cvNamedWindow(«tiff»,CV_WINDOW_AUTOSIZE);
// показываем картинку
cvShowImage(«tiff»,image);
cvShowImage(«original»,image2);
// ждём нажатия клавиши
cvWaitKey(0);
// освобождаем ресурсы
cvReleaseImage(&image);
cvReleaseImage(&image2);
cvReleaseImage(&src);
// удаляем окно
cvDestroyWindow(«original»);
cvDestroyWindow(«tiff»);
return 0;
}
Картинки sf.jpg и qwe.TIF лежат во всех возможных папках проекта. При запуске через F5 окно original отображает правильно картинку sf.jpg, а в окне tiff — серый экран (даже форма окна не подстроилась под форму картинки qwe.TIF).
Я убрал cvCloneImage для картинки qwe.TIF, поскольку с ней выдается вышеописанная ошибка с прерыванием программы.
cvShowImage почему-то не работает с моим qwe.TIF
увы — OpenCV нормально грузит только 8-битные tif-файлы
( https://code.ros.org/trac/opencv/ticket/116 )
только что проверил — это действительно так.
А как узнать, сколько бит в моем tif файле?
Но больше интересует следующее:
tif-файлы загружаются функцией TIFFOpen или TIFFReadRGBAImage(), а потому объект image должен иметь класс TIFF*, который, в свою очередь, не распознается функцией cvShowImage.
Все библиотеки tiff для OpenCV имеются у меня в наличии. Вопрос: какая функция заменяет cvShowImage для объектов класса TIFF* и файлов .tif, прикрепленных к ним посредством функции TIFFOpen или TIFFReadRGBAImage()?
Спасибо.
думаю тут два варианта — или посмотреть как это сделано в OpenCV — благо исходники открыты, либо разобраться в формате возвращаемых данных TIFF* и написать функцию-конвертер из TIFF в IplImage
сторонней программой. У меня, например, встроенный просмотрщик Total Commader-а выдаёт полную информацию о файле.
Спасибо! Попробуем сначала найти аналог cvShowImage для TIFF* в самом OpenCV.
Еще раз здравствуйте!
Я проверил работу вышеописанной программы на двух файлах tif глубиной 1 или 8 бит (черно-белое) или (градации серого). К сожалению, cvShowImage по-прежнему показывает пустое окно.
Играясь с преобразователем форматов AbleFaxTifView, я обнаружил, что функция cvShowImage отображает файлы tiff любой глубины, если они не меньше (!) чем 790 байт. Эта граница может быть чуть ниже, я еще не нашел ее минимальное значение, но tiff-файлы размером уже 9 байт не отображаются функцией cvShowImage
интересно 🙂
посредством множества магических манипуляций, я выяснил следующее:
Картинки, сохраненные из MS Paint или виндового окна «сохранить как» под форматом TIF или TIFF никогда не будут распознаны cvShowImage. Видимо на этом этапе возникают скрытые необратимые преобразования.
Картинки, приведенные к формату TIF или TIFF из других форматов посредством универсальной программы AbleFaxTifView (доступна в Open Source) могут быть отображены через cvShowImage при любом размере файла или глубине цвета. Полагаю, что через графические редакторы или Photoshop можно вполне безболезненно сохранять картинки в формате TIFF, так что они затем могут быть обработаны cvShowImage.
Все оказалось довольно нетривиально, но со счастливым концом :). Интересно, почему не работает ситуация из пункта 1, но это предмет дальнейших исследований. А пока начальство может быть спокойно. 🙂
Всем спасибо!
cvShowImage не читает TIFF-файлы, использующие LZW-сжатие.
Скажите, пожалуйста. А как можно реализовать следующую ситуацию: Пользователь вводит с клавиатуры путь к картинке, то есть значение filename, а затем программа запускается. Так, чтобы вводить путь не в самой программе.
Спасибо.
🙂 не вижу проблемы — всё зависит от того — что и как вы реализуете:
под консоль — просто выводите сообщение и считываете введённую строчку, под win32 — выдаёте окошко для выбора файла.
Кстати, а как это относится к OpenCV? 😉
Я пишу следующее:
char* filename=0;
printf(«Insert string: \n»);
scanf("%s",filename);
IplImage* image=0;
image=cvLoadImage(filename,1);
Не работает. Пишет, что неправильный указатель filename.
вы забыли выделить память под буфер filename, в котором собираетесь сохранять введённую строчку.
— обратите внимание, что используется ограниченный по длине массив, по-этому может быть реализованопереполнение буфера (buffer overflow).
Кстати, Вы не находите, что этот вопрос больше относится к основам программирования C/C++?
Спасибо. Но вопрос напрямую касается именно OpenCV. Переменная filename в функции cvLoadImage должна быть типа char* (не массив []), однако я пытаюсь ввести с клавиатуры её значение вручную так:
char* filename=(char*)calloc(256,sizeof(char));
scanf(«s%»,filename);
IplImage* image = cvLoadImage(filename,1);
сразу после ввода любой строки (ввожу путь к картинке), программа прерывается с ошибкой, что filename — не правильный указатель. Не понятно, функция cvLoadImage требует Массив или символ в качестве filename? Как же тогда сделать ввод строки символов с клавиатуры?
Спасибо.
всего-лишь опечатка (s%)
а раз мы всё-таки программируем на С++:
Ура, спасибо, работает! Вот только ещё стришок бы:
Если действовать Вашим путем, то приходится все картинки размещать в папке с проектом. А мне хотелось бы вводить путь типа Q:/Program Files/imgs/img1.tiff
Как только я такой ввожу, программа вылетает (без ошибки :)). Хотя такой путь я могу указать в самой программе, когда объявляю filename, и программа дальше работает, запускает cvLoadImage и всё остальное.
Такая проблем как-нибудь решается?
Спасибо.
Спасибо за уроки. Весьма полезны.вот это пречисление
Можете подсказать, что означают в константах задающих глубину цвета буквы U, S, F?
Точнее, пытаюсь сопоставить IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F и
Скажите пожалуйста, как избавиться от константности указателя filename в функции cvLoadImage(filename, 1) ??
Мне нужно передать в DLL в качестве этого самого filename строку символов, обозначающую путь к данной картинке, но это приводит к ошибке — «попытка чтения\записи в защищенную память». Нужно убрать свойство const char* filename, и заменить на char* filename. Как это сделать?
Сама функция cvLoadImage описана в файле loadsave.cpp OpenCV
Спасибо.
Здравствуйте!
1. Спасибо за лучшую русскоязычную информацию по opencv.
2. Возникла проблемма — может что подскажете.
Столкнулся с тем, что функция cvPyrMeanShiftFiltering корректно работает только в случае входного файла в цветовой гамме sRGB, если же файл в гамме Adobe RGB — функция просто оставляет входное изображение без изменений.
Какие есть варианты обхода такого поведения?
Думал о том — что-бы принудительно конвертировать RGB в sRGB, но средствами opencv или pil — не нашел как сделать.
Спасибо.
А как сделать так, чтобы не открывалась консоль, а только изображение?
это уже платформозависимые нюансы. если под Windows, то вместо консольного — создавайте виндовый проект и вперёд.
Здравствуйте, я новенькая в этой сфере… Работаю с студио2010, вот вопрос: допустим у меня есть черно-белое изображение, загрузила и выводится на консоль, все правильно работает… а как считать число белых или черных пикселей на изображение?
В принципе, можнообойти пиксели и посчитать «вручную», а если картинка действительно чёрно-белая, то можно использовать мат.-функции cvSum() или даже cvCountNonZero() .
Спасибо огромное, разбиралась, все понятно стало!!! наконец, после сессии вернулась я сюда! теперь у меня другие проблемы: мне надо построить гистограмму для черно-белой изображении, какую функцию можно тут использовать, с примерами использования если есть
см.Histograms форуме .
Вопросы, напрямую не относящиеся к статьям, лучше задавать на
откуда берется картинка? пытаюсь да пытаюсь вывести на экран картинку, но выдает или исключение, или, если закомментить исключение, серый экран. как быть?
Если запускаете из-под IDE, то картинка, обычно, должна лежать в каталоге проекта. Впрочем, ничто не мешает прописать абсолютный (полный) путь к файлу картинки.
спасибо)
Всем доброго дня!
Коллеги, может кто-нибудь объяснить зачем нужна следующая строка кода?
// клонируем картинку
src = cvCloneImage(image);
И почему без этой строки возникает ошибка выполнения?
Спасибо!
То есть хранит данные цвета в байтовом представлении?? То есть когда первый пиксель изображения красный то первые три char будут 255 0 0?
именно так. Только,данные хранятся не в формате RGB, а в формате BGR.
А если мне нужен еще и альфа канал?
он может быть четвёртым каналом — BGRA 😉
Ясно и надеюсь последний вопрос
допустим у меня есть bmp изображение в 1 пиксель (0, 255, 0), т.е.
Но на выходе получаю все тот же зеленый пиксель
все отбой, причина — кривые руки