Programação 23/24 S2
Laboratório 1
Regras
- Esta laboratório vale 1 valor (5%) da nota final da UC.
- O laboratório tem a duração de 1 hora e é individual.
- Para resolver os seguintes exercícios, podem ser usados:
- computador
- ambiente de desenvolvimento, sem assistências configuradas (e.g. Github Copilot)
- folha de rascunho
- caneta ou lápis
- folha de consulta “cheatsheet”
- Não podem ser consultados ou usados quaisquer outros recursos.
- Em cima da mesa de trabalho não devem estar quaisquer outros objetos, à excepção de uma garrafa de água, se desejado.
- O incumprimento das regras supracitadas levará à anulação do laboratório e consequente atribuição de pontuação 0.
- Lê o enunciado com atenção e usa o código fornecido quando apropriado.
Exercício 1 - IoU [60%]
Contexto
Na área de visão computacional, em particular na deteção de objetos, a métrica Intersection over Union (IoU) mede a área da interseção entre uma deteção positiva de um objecto de interesse e as características verdadeiras desse mesmo objecto. A deteção é especificada por uma bounding box (BB).
O cálculo de IoU é feita da seguinta foram:
IoU = \frac{A_I}{A_U}
A_U = A_1 + A_2 - A_I
Onde:
- A_I -> área da interção
- A_U -> área da união
- A_1 -> área da BB 1
- A_2 -> área da BB 2
Objetivo
Escreve uma função chamada compute_iou
que calcula a IoU a partir das coordenadas das 2 bounding boxes, onde:
- BB 1 é definida por (x11, y11) para o canto superior esquerdo e (x12, y12) para o canto inferior direito
- BB 2 é definida por (x21, y21) para o canto superior esquerdo e (x22, y22) para o canto inferior direito
Esta função deve portanto receber 8 números inteiros (correspondentes às 2 BB) e devolver um número real (IoU).
O funcionamento desta função pode ser validado com a lista no código fornecido. Em cada linha está um par de BB e o último valor é a IoU correspondente, i.e. \{x11, y11, x12, y12, x21, y21, x22, y22, iou\}.
Ajudas:
- para calcular a área de uma BB, é necessário calcular a altura e a largura, e multiplicar esses 2 valores;
- para calcular a área da interseção, é necessário calcular as dimensões do rectângulo interno, i.e.:
- a largura é a diferença entre o máximo dos cantos esquerdos (x11, x21) e o mínimo dos cantos direitos (x12, x22);
- altura é a diferença entre o máximo dos cantos superiores (y11, y21) e o mínimo dos cantos inferiores (y12, y22);
- atenção à direção dos eixos x e y;
- é necessário confirmar que existe interseção!
Exercício 2 - IoU Média [40%]
Na função main
, implementa um programa completo que
- leia 50 pares de BB;
- calcule a IoU com a função implementada no exercício 1 para cada par;
- mostre na consola os parâmetros das BB e corerspondente IoU, e.g.
BB 1: 478, 371, 754, 435 BB 2: 542, 381, 729, 424 IoU:0.4594
(não é necessário especial cuidado com a formatação de números reais); - calcule a média de todas as IoU e apresente o valor na consola no final.
No código fornecido, existe uma função que quando invocada devolve um par de BB. Contudo, o valor fornecido utiliza registos. Para extrair os detalhes de cada BB, pode-se usar a seguinte lógica:
// como receber 1 par de bounding boxes
BBoxPair bb = fetch_next_bounding_box_pair();
// bb 1
int x11 = bb.x11, y11 = bb.y11, x12 = bb.x12, y12 = bb.y12;
// bb 2
int x21 = bb.x21, y21 = bb.y21, x22 = bb.x22, y22 = bb.y22;
Ajudas:
- É necessário implementar um ciclo e usar a lógica de leitura de BB durante 50 iterações.
- Se o exercício 2 não foi resolvido, pode-se usar os valores da IoU de cada par já previamente calculados para validação e usar esse valor para o cálculo da média, com um desconto de 25%, e.g.
Código fornecido - copiar
#include <stdio.h>
typedef struct {
int x11, y11, x12, y12, x21, y21, x22, y22;
float iou;
} BBoxPair;
BBoxPair bbs[] = {
// { x11, y11, x12, y12, x21, y21, x22, y22, iou}
{ 478, 371, 754, 435, 542, 381, 729, 424, 0.45942793668425436 },
{ 303, 261, 615, 313, 325, 272, 513, 303, 0.36457893785038276 },
{ 604, 100, 658, 173, 604, 118, 638, 164, 0.40417690417690416 },
{ 119, 249, 497, 318, 185, 279, 400, 318, 0.3256690539012439 },
{ 191, 353, 394, 430, 229, 360, 385, 419, 0.5920060331825038 },
{ 289, 95, 648, 129, 335, 98, 538, 118, 0.34 },
{ 125, 452, 723, 489, 195, 465, 451, 485, 0.23710570248660048 },
{ 412, 19, 657, 499, 413, 50, 595, 406, 0.5521271740783936 },
{ 326, 75, 655, 99, 371, 78, 654, 98, 0.722909090909091 },
{ 768, 448, 788, 501, 768, 457, 788, 497, 0.7592592592592593 },
{ 160, 178, 241, 321, 165, 188, 215, 277, 0.38871951219512196 },
{ 125, 410, 150, 482, 130, 426, 150, 465, 0.44257112750263433 },
{ 221, 153, 422, 523, 324, 252, 405, 401, 0.16412692482186225 },
{ 397, 190, 705, 431, 443, 196, 695, 393, 0.6699029126213593 },
{ 730, 332, 755, 410, 730, 338, 751, 403, 0.7069133398247323 },
{ 747, 281, 797, 413, 752, 301, 790, 401, 0.5807164971251658 },
{ 5, 478, 751, 500, 30, 478, 715, 498, 0.8384843722716955 },
{ 553, 318, 656, 490, 580, 323, 637, 419, 0.3126945309026234 },
{ 733, 357, 791, 479, 754, 388, 785, 453, 0.2910293509714758 },
{ 451, 501, 474, 524, 454, 504, 474, 524, 0.765625 },
{ 524, 489, 748, 532, 562, 489, 736, 522, 0.601010101010101 },
{ 227, 160, 375, 511, 265, 260, 369, 507, 0.49649176327028677 },
{ 589, 406, 720, 504, 599, 440, 675, 497, 0.34175084175084175 },
{ 149, 289, 651, 517, 189, 392, 443, 507, 0.25679981247883876 },
{ 689, 346, 713, 366, 690, 346, 712, 366, 0.92 },
{ 82, 187, 126, 472, 85, 193, 123, 441, 0.7545454545454545 },
{ 477, 181, 699, 298, 566, 206, 695, 274, 0.34088318005624385 },
{ 492, 339, 543, 490, 495, 350, 542, 490, 0.8562753036437247 },
{ 694, 7, 799, 372, 697, 7, 795, 347, 0.8701670275286112 },
{ 481, 75, 704, 357, 494, 84, 674, 312, 0.6538522211004543 },
{ 91, 66, 406, 195, 133, 74, 377, 174, 0.6023612463485881 },
{ 504, 380, 594, 419, 515, 380, 587, 411, 0.6417582417582418 },
{ 724, 0, 764, 301, 730, 7, 752, 178, 0.3194960426425456 },
{ 149, 241, 563, 435, 281, 245, 558, 374, 0.4465863453815261 },
{ 763, 105, 795, 296, 767, 166, 787, 278, 0.37452651515151514 },
{ 559, 125, 711, 166, 567, 137, 670, 164, 0.4531590413943355 },
{ 288, 379, 726, 453, 299, 387, 687, 452, 0.7797722095671982 },
{ 358, 213, 647, 280, 368, 229, 580, 278, 0.5400608519269777 },
{ 647, 173, 728, 233, 665, 202, 690, 222, 0.10915633746501399 },
{ 360, 251, 576, 506, 366, 288, 546, 500, 0.6939984158986175 },
{ 72, 357, 673, 508, 260, 420, 564, 496, 0.25665544675642593 },
{ 645, 81, 691, 495, 652, 138, 690, 487, 0.699820558831069 },
{ 592, 458, 623, 508, 601, 462, 621, 490, 0.37316176470588236 },
{ 78, 140, 499, 197, 132, 150, 431, 190, 0.5025330936427521 },
{ 354, 443, 609, 528, 425, 451, 581, 503, 0.37795239825581395 },
{ 624, 359, 683, 428, 635, 383, 667, 420, 0.2985714285714286 },
{ 201, 272, 733, 329, 470, 286, 691, 309, 0.17234909749628 },
{ 571, 349, 800, 505, 603, 376, 782, 498, 0.6131265577402382 },
{ 608, 389, 709, 468, 608, 405, 673, 456, 0.42058823529411765 },
{ 605, 184, 659, 344, 606, 186, 647, 308, 0.583399209486166 },
};
int fetched_i=0;
// esta função simula a leitura de um par de bounding boxes
// sempre que for chamada, devolve um novo par de bounding boxes
// até que não haja mais pares para devolver
BBoxPair fetch_next_bounding_box_pair() {
if (fetched_i >= sizeof(bbs)/sizeof(bbs[0])) {
fetched_i = 0;
}
return bbs[fetched_i++];
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * *
Função exercício 1 - calcular IoU
* * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * */
// escrever aqui a função do exercício 1
int main() {
// NOTA
// para o exercício 1, este código é inútil
// escreve uma main diferente para verificar o funcionamento
// da função do exercício 1
int x11, y11, x12, y12, x21, y21, x22, y22;
float iou;
// como receber primeiro par de bounding boxes
BBoxPair bb = fetch_next_bounding_box_pair();
// bb 1
x11 = bb.x11, y11 = bb.y11, x12 = bb.x12, y12 = bb.y12;
// bb 2
x21 = bb.x21, y21 = bb.y21, x22 = bb.x22, y22 = bb.y22;
printf("par 1: x11=%d, y11=%d, ...\n", x11, y11);
// como receber segundo par de bounding boxes
bb = fetch_next_bounding_box_pair();
x11 = bb.x11, y11 = bb.y11, x12 = bb.x12, y12 = bb.y12;
x21 = bb.x21, y21 = bb.y21, x22 = bb.x22, y22 = bb.y22;
printf("par 2: x11=%d, y11=%d, ...\n", x11, y11);
return 0;
}