Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Основы opencv (на с++)
- ## Вместо вступления
- Это рукодоство должно дать базовые знания об opencv, с помощью которых можно искать решения практических задач в интернете (или посмотреть в этой репе). Не рекомендуется смотреть полные руководства в интернете, т.к. большинство из них используют старую версию opencv с другими типами переменных, которые несовместимы с новыми функциями. Полная документация к opencv доступна [тут](https://docs.opencv.org/).
- ## Что такое opencv?
- Opencv (OPEN source Computer Vision library) - библиотека для компьютерного зрения (оно же видеозрение и техническое зрение), т.е. для обнаружения и классификации объектов на изображении. Реализована на c++, java, python, ruby, matlab и lua.
- ## Opencv на python
- `opencv-python` - название opencv в pip
- `cv2` - название модуля opencv
- Изображение - массив numpy в формате BGR, т.е. RGB наоборот.
- `cv2.VideoCapture` - класс, читающий кадры с камеры или из видео
- `cap = cv2.VideoCapture(0)` - откроет камеру #0. `cap = cv2.VideoCapture('videos/vid.mp4')` - откроет видео
- `_, frame = cap.read()` - прочитает кадр из `cap`.
- `cv2.imshow("hello world", frame)` - покажет frame в окне с именем hello world.
- Дальше сами разберетесь, не маленькие уже. В дальнейшем речь идет об opencv на c++
- ## Hello world
- Напишем самую простую программу - которая выводит на экран видеопоток с камеры
- Для начала, подключим заголовки opencv и прочую шнягу (предполагается, что opencv уже скомпилировано, если ты под линуксом или проект сконфигурирован, если ты под виндой)
- Если opencv еще не скомпилировано, то читаем это руководство: [Компиляция opencv для Linux](Компиляция opencv для Linux)
- ```c++
- #include "opencv2/opencv.hpp"
- using namespace cv;
- ```
- Все функции и классы в opencv завернуты в namespace cv
- Видеопоток в opencv имеет тип `VideoCapture`. Это класс, который способен открывать видео и выдавать изображение по кадрам. Открытие видео с камеры осуществляется через метод `.open(int device)`, где `device` - номер камеры, с которой снимается видео. Его проще всего находить подбором, обычно это 0.
- Итак, создание объекта типа `VideoCapture` и открытие видео выглядят вот так (это, очевидно, в `main`):
- ```c++
- VideoCapture cap;
- cap.open(0);
- ```
- Также можно открывать видео, прописав в `.open()` вместо номера камеры путь к файлу видео, например `cap.open("videos/vid.mp4");`
- Теперь мы хотим получить изображение из видеопотока. Это делается при помощи оператора `>>`, и изображение записывается в объект класса `Mat` - матрица, класс для изображений в opencv. Так как мы хотим получить не одно изображение, а считывать их с камеры постоянно, то мы будем это делать в бесконечном цикле. Также необходимо объявить матрицу.
- ```c++
- Mat img;
- while(true)
- {
- cap >> img;
- }
- ```
- Мы получаем изображение из видеопотока, теперь нужно его вывести на экран. Для этого есть функция `imshow(std::string winname, Mat input)`. Она выводит изображение `input` в окно с названием `winname`. Также нужно вызвать фунцкию `waitKey(int msec)`, которая ждет нажатия кнопки на клавиатуре пользователя, чтобы окно отрисовалось.
- ```c++
- imshow("Hello world!", img);
- waitKey(1);
- ```
- Если ты все переписал правильно и в нужном порядке, то у тебя появилось окно, в котором видно изображение с камеры. Если нет, то попроси кого-нибудь, кто свободен и разбирается в opencv, тебе помочь.
- Ты поверхностно познакомился с `VideoCapture` и `Mat`. Теперь посмотрим на них чуть более детально.
- ## VideoCapture
- У `VideoCapture` есть полезный метод - `isOpened()`. Его можно использовать, чтобы проверять, что видеопоток открылся нормально, например:
- ```c++
- if (!cap.isOpened())
- {
- std::cout << "Could not open the capture" << std::endl;
- return -1;
- }
- ```
- Также можно использовать ip-камеры, которые передают видео через wi-fi, например `cap.open("http:\\10.0.1.2\video.mpeg");`
- ## Mat
- Изображения можно читать из файла с помощью функции `imread(std::string filename)`, например `Mat img = imread("imgs/saple.img");`
- `.data` возвращает указатель на сырые данные изображения. Хотя он редко используется, он полезен для проверки, есть ли в изображении какие-либо данные, например:
- ```c++
- if(!img.data)
- {
- std::cout << "The image is empty" << std::endl;
- return -1;
- }
- ```
- Изображения в opencv хранятся в формате BGR, то есть RGB наоборот. В другие форматы можно переводить при помощи `cvtColor(Mat input, Mat output, int code)`, например `cvtColor(img, imgHSV, CV_BGR2HSV)`. Такой перевод может понадобиться, например, для выделения объекта по его цвету (colorfind.cpp)
- Размер матрицы можно получить с помощью `.size()`, который возвращает объект типа `Size`, о котором будет сказано в следующей части. Также её размер можно получить при помощи `.cols` и `.rows`, которые возвращают число рядов и столбцов соответственно.
- К пикселям из `Mat` можно обращаться через `.at()`, как в этом цикле по всем пикслеям (он не протестирован, возможно нужно поменять местами `cols` и `rows`):
- ```c++
- for (int x = 0; x < img.cols; x++)
- {
- for (int y = 0; y < img.rows; y++)
- {
- Scalar color = img.at<Vec3b>(y, x);
- //что-то делаем с color
- }
- }
- ```
- Тут ты столкнулся с двумя новым типами - `Scalar` и `Vec3b`, что ведет нас к следующей части.
- ## Прочие классы в opencv
- `Scalar` - класс, содержащий в себе 4 элемента любого типа, доступ к которым осуществляется через `[]`. `Vec` - множество классов, состоящих из `n` элементов, где `n` - число, стоящее после `Vec`. Тип у этих элементов задается буквой, стоящей после `n`.
- | Буква | Тип |
- |:-----:|:------:|
- | b | byte |
- | i | int |
- | s | short |
- | f | float |
- | d | double |
- Например, `Vec3b` - класс из трёх элементов типа byte.
- Как несложно догадаться, `Scalar` - дочерний класс `Vec`. Зачем он сделан - непонятно.
- `Point` - класс, также часто использующийся в opencv. Обозначает он - ты не поверишь - точку. Он похож на `Vec` тем, что задается аналогично - число, стоящее после `Point`, обозначает число элементов в нем, а буква после этого обозначает тип данных. Но обращение к данным осуществляется через `.x`, `.y` и `.z`. Также на `Point` заданы операции сложения, вычитания и деления.
- `Size` - класс для обозначения размеров изображения или прямоугольника. `.width` и `.height` - ширина и высота соответственно.
- ## Заключение
- Все дальнейшее можно узнать, почитав документацию по opencv вот [тут](docs.opencv.org). Если что непонятно и не гуглится, всегда можно спросить кого-нибудь из лабы. И не забывайте заглядывать в usefulcode, возможно ваша задача там уже решена.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement