Exploração preliminar dos principais componentes: estrutura de dados OpenCV e desenho básico

1. Contêiner de imagens básico Mat

1.1 Visão geral do armazenamento de imagens digitais

Temos vários métodos de aquisição de imagens digitais do mundo real: câmeras digitais, scanners, tomografia computadorizada e ressonância magnética, para citar alguns. Em cada caso, o que nós (humanos) vemos são imagens. No entanto, ao traduzir isso para nossos dispositivos digitais, o que registramos é o valor numérico de cada ponto da imagem.
insira a descrição da imagem aqui
Por exemplo, na imagem acima, você pode ver que o retrovisor do carro nada mais é do que uma matriz contendo os valores de intensidade de todos os pixels. A forma como obtemos e armazenamos valores de pixel pode variar de acordo com nossas necessidades, mas no final das contas todas as imagens no mundo da informática podem ser reduzidas a uma matriz de números e outras informações que descrevem a própria matriz.

1.2 Uso do Tapete

Sobre a classe Mat primeiro precisamos saber:

  1. Você não precisa alocar espaço manualmente para ele
  2. O espaço não precisa ser liberado imediatamente quando não é necessário

A maioria das funções do OpenCV aloca automaticamente o espaço necessário para seus dados de saída. Se passar um objeto Mat já existente, que já tenha alocado o espaço necessário para a matriz, este será reaproveitado. Em outras palavras, usamos apenas a memória necessária para realizar a tarefa a qualquer momento.
Mat é basicamente uma classe com duas partes de dados: o cabeçalho da matriz (contendo informações como o tamanho da matriz, o método usado para armazenamento, em qual endereço a matriz está armazenada etc.) os valores de pixel (Tome qualquer tamanho, dependendo do método de armazenamento escolhido). O tamanho do cabeçalho da matriz é constante, mas o tamanho da própria matriz pode variar de imagem para imagem e geralmente é muito maior.
Para resolver este problema, o OpenCV usa um sistema de contagem de referências. A ideia é que cada objeto Mat tenha seu próprio cabeçalho, mas uma matriz pode ser compartilhada entre dois objetos Mat, desde que seus ponteiros de matriz apontem para o mesmo endereço . Além disso, o operador de cópia copiará apenas o cabeçalho e os ponteiros para a matriz grande, não os dados em si.

Pergunta: Se a matriz pertencer a vários objetos Mat, quem é responsável por limpá-la quando ela não for mais necessária?
O último objeto que a utilizou. Isso é obtido por meio do mecanismo do contador de referência. Sempre que copiarmos o cabeçalho de informação de um objeto Mat, aumentaremos o número de referências à matriz. Por outro lado, quando um cabeçalho é liberado, a contagem é decrementada em um; quando a contagem é 0, a matriz é limpa.
Mas às vezes você quer copiar a própria matriz, neste momento você pode usar a função clone() ou copyTo()

1.3 Método de armazenamento do valor do pixel

  • O espaço de cores RGB é o espaço de cores mais comumente usado. Isso se deve ao fato de que também é a maneira como o olho humano compõe as cores. Suas cores primárias são vermelho, verde e azul. Às vezes, um quarto elemento alfa (A)
    é adicionado para representar cores transparentes.
  • HSV e HLS dividem as cores em matiz, saturação e luminosidade. Esta é uma forma mais natural de descrever as cores, por exemplo, descartando o último elemento, tornando o algoritmo insensível às condições de iluminação da imagem de entrada.
  • YCrCb é amplamente utilizado no formato de imagem JPEG
  • COE L a b* é um espaço de cor perceptivamente uniforme adequado para medir a distância entre duas cores.

1.4 Exibição criando objeto Mat

  1. Use o construtor Mat()
	Mat M(2, 2, CV_8UC3, Scalar(0, 0, 255));
	cout << "M=" << endl << " " << M << endl << endl;

insira a descrição da imagem aqui
Para uma imagem multicanal bidimensional, primeiro defina suas dimensões, ou seja, linhas e colunas. Em seguida, você precisa especificar o tipo de dados dos elementos de armazenamento e o número de canais para cada ponto da matriz.

CV_[número de dígitos[assinado ou não][tipo de prefixo]C[número de canais]
Por exemplo, CV_8UC3 significa usar o tipo de caractere não assinado de 8 bits e cada pixel consiste em três pixels para formar três canais. O número de canais predefinidos pode ser de até quatro. Além disso, Scalar é um vetor curto que pode ser usado para inicializar uma matriz com um valor personalizado especificado e também pode ser usado para representar uma cor.

  1. Use matrizes C/C++ e inicialize-as por meio de construtores
    int sz[3] = {
    
    2,2,2};
    Mat L(3,sz, CV_8UC(1), Scalar::all(0));

O exemplo acima demonstra como criar uma matriz com mais de duas dimensões: especifique as dimensões e passe um ponteiro para um array contendo as dimensões de cada dimensão.

  1. Use a função criar()
	Mat M;
	M.create(4, 4, CV_8UC(2));
	cout << "M=" << endl<< M << endl;

insira a descrição da imagem aqui
Este método de criação não pode definir o valor inicial para a matriz, mas apenas reabre a memória para os dados da matriz quando o tamanho é alterado.

  1. Usando o método de inicialização no estilo Matlab
	Mat E = Mat::eye(4, 4, CV_64F);
	cout << "E=" << endl << " " << E << endl << endl;
	Mat O = Mat::ones(2, 2, CV_32F);
	cout << "O=" << endl << " " << O << endl << endl;
	Mat Z = Mat::zeros(3, 3, CV_8UC1);
	cout << "Z=" << endl << " " << Z << endl << endl;

insira a descrição da imagem aqui

2. Estruturas e funções de dados comumente usadas

2.1 Representação de ponto: classe de ponto

A estrutura de dados da classe Point representa um ponto em um sistema de coordenadas bidimensional, ou seja, um ponto 2D especificado por suas coordenadas de imagem x e y.

	Point point;
	point.x=10;
	point.y=8
	//或者
	Point point=Point(10,8);

OpenCV tem a seguinte definição:

typedef Point_<int> Point2i;
typedef Point2i Point;
typedef Point_<float> Point2f;

Portanto, Point<int>, Point2i e Point são equivalentes entre si e Point_<float>, Point2f são equivalentes entre si.

2.3 Representação da cor: Classe escalar

Scalar() representa um array com quatro elementos, que é amplamente utilizado no OpenCV para passar valores de pixel, como valores de cores RGB. O valor da cor RGB tem três parâmetros. Na verdade, para a função Scalar, se o quarto parâmetro não for usado, você não precisa escrevê-lo; se você escrever apenas três parâmetros, o OpenCV pensará que representamos três parâmetros.

Se Scalar(a,b,c) for fornecido
, então os valores de cor RGB definidos: c para o componente vermelho, b para o componente verde e a para o componente azul.

2.4 Representação de tamanho: Classe de tamanho

Size(width,heigth)
Size(5,5)
constrói Size com largura e altura de 5,
ou seja, XXX.width=5, XXX.height=5

2.5 Representação de um retângulo: a classe Rect

As variáveis ​​de membro da classe Rect incluem x, y, largura e altura, que são as coordenadas do canto superior esquerdo e a largura e altura do retângulo, respectivamente.

As funções de membro comumente usadas são:
Size() retorna Size;
area(), retorna a área do retângulo;
contains(Point) determina se o ponto está dentro do retângulo;
inside(Rect) determina se o retângulo está dentro do retângulo retângulo
tl() retorna o canto superior esquerdo As coordenadas do ponto de
br() retornam as coordenadas do ponto do canto inferior direito
Encontre a interseção de dois retângulos: Rect rect = rect1 & rect2;
encontre a união de dois retângulos: Rect rect = rect1 | rect2;
operação de translação: Rect rectShift = rect + point;
operação de zoom:Rect rectSccale = rect + size;

2.5 Conversão do espaço de cores: função cvtColor()

A função cvtColor() é uma função de conversão de espaço de cores no OpenCV, que pode converter cores RGB em HSV, HSI e outros espaços de cores, e também pode ser convertida em imagens em tons de cinza.
void cvtColor(InputArray src, OutputArray dst,int code, int dstCn=0)

  • O primeiro parâmetro: a imagem de entrada
  • O segundo parâmetro: a imagem de saída
  • O terceiro parâmetro: o identificador da conversão do espaço de cores
  • O quarto parâmetro: o número de canais da imagem de destino, se este parâmetro for 0, significa que a imagem de destino leva o número de canais da imagem de origem.
    Por exemplo:cvtColor(srcImage,dstImage,COLOR_GRAY2BGR)
    insira a descrição da imagem aqui

3. Desenho de gráficos básicos

  • A função de linha para desenhar linhas retas
  • função elipse para desenhar elipses
  • A função retângulo para desenhar retângulos
  • função de círculo para desenhar círculos
  • A função fillPoly usada para desenhar polígonos preenchidos
    Defina várias funções de desenho personalizadas e, em seguida, chame essas funções personalizadas para desenhar uma figura: um mapa de átomos químicos.

definição de macro do programa
#define WINDOW_WIDTH 600 //定义窗口大小

3.1 Como escrever a função DrawEllipse()

//自定义绘制函数:实现了绘制不同角度、相同尺寸的椭圆
void DrawEllipse(Mat img, double angle) {
    
    
	int thickness = 2;
	int lineType = 8;
	ellipse(img,
		Point(WINDOW_WIDTH / 2, WINDOW_WIDTH / 2),
		Size(WINDOW_WIDTH/4,WINDOW_WIDTH/16),
		angle,
		0,
		360,
		Scalar(255,129,0),
		thickness,
		lineType
		);
}

Os parâmetros da função elipse e seus significados:
insira a descrição da imagem aqui

3.2 Como escrever a função DrawFilledCircle()

//自定义的绘制函数,实现了实心圆的绘制
void DrawFilledCircle(Mat img, Point center) {
    
    
	int thickness = -1;
	int lineType = 8;

	circle(img,
		center,
		WINDOW_WIDTH / 32,
		Scalar(0, 0, 255),
		thickness,
		lineType
	);
}

insira a descrição da imagem aqui

3.3 Função main()

#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
#define WINDOW_WIDTH 600
#define WINDOW_NAME "绘制图"
int main() {
    
    
	Mat atomImage = Mat::zeros(WINDOW_WIDTH, WINDOW_WIDTH, CV_8UC3);

	//1.1:绘制椭圆
	DrawEllipse(atomImage, 90);
	DrawEllipse(atomImage, 0);
	DrawEllipse(atomImage, 45);
	DrawEllipse(atomImage, -45);

	//1.2:绘制圆心
	DrawFilledCircle(atomImage, Point(WINDOW_WIDTH / 2, WINDOW_WIDTH / 2));

	imshow(WINDOW_NAME, atomImage);
	
	waitKey(0);
}

insira a descrição da imagem aqui

Acho que você gosta

Origin blog.csdn.net/m0_50127633/article/details/131201269
Recomendado
Clasificación