OpenCV em C

30 de janeiro de 2022 Off Por Marcelo Martins

Em um artigo anterior fiz um exemplo de opencv em Python.

OpenCV em Python

Neste artigo irei apresentar um exemplo de código de opencv em C++.

Irei comentar traçando referencias entre o código do C e o código do python.

O Exemplo utililizado será fornecido pela própria biblioteca em python.

Aqui vemos o exemplo comentado do fonte

OpenCV em Python

Para traçar um paralelo usaremos os códigos do opencv, o programa chamado video_v4l2.py

Conforme apresentado abaixo:

#!/usr/bin/env python

'''
VideoCapture sample showcasing  some features of the Video4Linux2 backend

Sample shows how VideoCapture class can be used to control parameters
of a webcam such as focus or framerate.
Also the sample provides an example how to access raw images delivered
by the hardware to get a grayscale image in a very efficient fashion.

Keys:
    ESC    - exit
    g      - toggle optimized grayscale conversion

'''

# Python 2/3 compatibility
from __future__ import print_function

import numpy as np
import cv2 as cv

def main():

    def decode_fourcc(v):
        v = int(v)
        return "".join([chr((v >> 8 * i) & 0xFF) for i in range(4)])

    font = cv.FONT_HERSHEY_SIMPLEX
    color = (0, 255, 0)

    cap = cv.VideoCapture(0)
    cap.set(cv.CAP_PROP_AUTOFOCUS, 0)  # Known bug: https://github.com/opencv/opencv/pull/5474

    cv.namedWindow("Video")

    convert_rgb = True
    fps = int(cap.get(cv.CAP_PROP_FPS))
    focus = int(min(cap.get(cv.CAP_PROP_FOCUS) * 100, 2**31-1))  # ceil focus to C_LONG as Python3 int can go to +inf

    cv.createTrackbar("FPS", "Video", fps, 30, lambda v: cap.set(cv.CAP_PROP_FPS, v))
    cv.createTrackbar("Focus", "Video", focus, 100, lambda v: cap.set(cv.CAP_PROP_FOCUS, v / 100))

    while True:
        _status, img = cap.read()

        fourcc = decode_fourcc(cap.get(cv.CAP_PROP_FOURCC))

        fps = cap.get(cv.CAP_PROP_FPS)

        if not bool(cap.get(cv.CAP_PROP_CONVERT_RGB)):
            if fourcc == "MJPG":
                img = cv.imdecode(img, cv.IMREAD_GRAYSCALE)
            elif fourcc == "YUYV":
                img = cv.cvtColor(img, cv.COLOR_YUV2GRAY_YUYV)
            else:
                print("unsupported format")
                break

        cv.putText(img, "Mode: {}".format(fourcc), (15, 40), font, 1.0, color)
        cv.putText(img, "FPS: {}".format(fps), (15, 80), font, 1.0, color)
        cv.imshow("Video", img)

        k = cv.waitKey(1)

        if k == 27:
            break
        elif k == ord('g'):
            convert_rgb = not convert_rgb
            cap.set(cv.CAP_PROP_CONVERT_RGB, 1 if convert_rgb else 0)

    print('Done')


if __name__ == '__main__':
    print(__doc__)
    main()
    cv.destroyAllWindows()

A primeira informação importante é a carga das bibliotecas do opencv em python.

import cv2 as cvimport cv2 as cv

carga da lib em python

O proximo ponto importante é onde capturamos o vídeo.

cap = cv.VideoCapture(0)

Captura do vídeo

O Parametro 0, indica que o device de vídeo é o padrão do sistema.

O ponto importante no código é o uso do cap, no código abaixo:

_status, img = cap.read()

captura do frame

Ao chamar a função read, dois parametros são retornados, _status (retorno de sucesso) e img, a imagem capturada.

Por fim, uma janela é montada com a visualização da imagem capturada:

cv.imshow(“Video”, img)

janela é montada

Agora iremos analisar o mesmo código em C.

OpenCV em C

Agora mostraremos o código em C, o exemplo é o videocapture_basic.cpp:


#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <stdio.h>

using namespace cv;
using namespace std;

int main(int, char**)
{
    Mat frame;
    //--- INITIALIZE VIDEOCAPTURE
    VideoCapture cap;
    // open the default camera using default API
    // cap.open(0);
    // OR advance usage: select any API backend
    int deviceID = 0;             // 0 = open default camera
    int apiID = cv::CAP_ANY;      // 0 = autodetect default API
    // open selected camera using selected API
    cap.open(deviceID, apiID);
    // check if we succeeded
    if (!cap.isOpened()) {
        cerr << "ERROR! Unable to open camera\n";
        return -1;
    }

    //--- GRAB AND WRITE LOOP
    cout << "Start grabbing" << endl
        << "Press any key to terminate" << endl;
    for (;;)
    {
        // wait for a new frame from camera and store it into 'frame'
        cap.read(frame);
        // check if we succeeded
        if (frame.empty()) {
            cerr << "ERROR! blank frame grabbed\n";
            break;
        }
        // show live and wait for a key with timeout long enough to show images
        imshow("Live", frame);
        if (waitKey(5) >= 0)
            break;
    }
    // the camera will be deinitialized automatically in VideoCapture destructor
    return 0;
}

O primeiro ponto assim como no código em python, e a chamada da biblioteca em c.

#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>

Sem esses includes não teriamos acessos aos tipos do C, como o que segue:

VideoCapture cap;

O tipo VideoCapture é o tipo associado a captura de vídeo da câmera.

Onde usaremos, conforme fragmento abaixo:

int deviceID = 0;             // 0 = open default camera
int apiID = cv::CAP_ANY;      // 0 = autodetect default API
// open selected camera using selected API
cap.open(deviceID, apiID);

Aqui, definimos o deviceID como 0, ou seja, o valor padrão, veja a semelhança do uso do python.

E apiID, passando o escopo (variavel) CAP_ANY, que tem por valor 0.

Chamamos o método open da classe VideoCapture, indicando o deviceID, e o apiID.

Agora iremos ler a imagem da camera, que podemos fazer, através da seguinte função:

cap.read(frame);

Neste fragmento de código, passamos o parametro frame, que é do tipo Mat.

O frame receberá a imagem capturada.

E por fim, no código abaixo a janela que irá mostrar a imagem na interface gráfica.

imshow("Live", frame);

Conclusão

Apesar das diferenças de linguagem, podemos ver o pontos em comum, e a sutileza da semelhança.

É lógico que os códigos foram escolhidos a dedo. Justamente por conta da semelhança e simplicidade.

O opencv é uma biblioteca rica, cheia de opções e dificuldades, este tutorial, bem como o autor, esta apenas adentrando neste mundo para mim misterioso.

Espero que tenham gostado deste artigo. 😉