Por que funciona: Unidade 1.2: Captura da imagem, Unidade 1.3: A imagem como dado

Recortar, redimensionar e salvar uma imagem no OpenCV

Termine a correção: recorte a carta de cores com fatiamento de array, reduza a foto com cv2.resize e INTER_AREA e salve com cv2.imwrite, onde a mesma imagem tem 54 KB como JPEG e 276 KB como PNG.

Luis Condados · · 3 min de leitura Iniciante

Tradução assistida por máquina do original em inglês. Números, código e referências foram conferidos com ele; o texto não foi revisado por um falante nativo. Ler o original. Os labs interativos e o código estão em inglês.

A carta de cores e o braço do abajur, recortados da foto corrigida.
A carta de cores e o braço do abajur, recortados da foto corrigida.

Recortar guarda uma parte da foto, redimensionar muda quantos pixels ela tem e salvar a grava num arquivo. Esta lição faz as três coisas com a foto corrigida.

A foto corrigida do abajur ao lado de um recorte da sua carta de cores e do braço do abajur.
À esquerda: a foto depois da correção da lição 3, 960 × 639. À direita: as linhas 150 a 449 e as colunas 0 a 329 dela. Quadro do HDR Photographic Survey [3].

Onde você já viu isso: a ferramenta Cortar de qualquer app de fotos; as opções de tamanho e qualidade de Exportar ou Salvar como em qualquer editor de imagem.

TL;DR. Um recorte é uma fatia do array, um redimensionamento recebe o tamanho como largura e depois altura, e o formato do arquivo decide o tamanho da imagem salva. A foto corrigida fica com 54 KB em JPEG com qualidade 90 e 276 KB em PNG.

O problema

A correção da lição 3, multiplicar por 2,4, é a que o projeto mantém. Esta é a última etapa do projeto. Falta o que você faria com qualquer foto antes de compartilhar: ficar com a parte interessante, deixá-la menor e gravá-la num arquivo.

Recortar, redimensionar, salvar

Um recorte não precisa de função. A imagem é um array (lição 1), então fixed[150:450, 0:330] são as linhas 150 a 449 e as colunas 0 a 329: a carta de cores e o braço do abajur. cv2.resize recebe o novo tamanho como (largura, altura) e um método de interpolação; o tutorial do OpenCV recomenda INTER_AREA para reduzir [1]. cv2.imwrite escolhe o formato pelo nome do arquivo e recebe as opções do formato como uma lista [2].

Python · OpenCV
import os
import cv2

fixed = cv2.convertScaleAbs(cv2.imread("dark.webp"), alpha=2.4)
chart = fixed[150:450, 0:330]  # linhas 150-449, colunas 0-329
thumb = cv2.resize(fixed, (480, 320), interpolation=cv2.INTER_AREA)

cv2.imwrite("fixed.jpg", fixed, [cv2.IMWRITE_JPEG_QUALITY, 90])
cv2.imwrite("fixed.png", fixed)
for name in ("fixed.jpg", "fixed.png"):
    print(name, os.path.getsize(name) // 1024, "KB")
cv2.imshow("the crop", chart)
cv2.imshow("the thumbnail", thumb)
Saída
fixed.jpg 54 KB
fixed.png 276 KB
the crop
the crop
the thumbnail
the thumbnail
ChamadaO que faz
img[r0:r1, c0:c1]um recorte: linhas r0 a r1 - 1, colunas c0 a c1 - 1
cv2.resize(img, (w, h), interpolation=cv2.INTER_AREA)um novo tamanho, largura primeiro; INTER_AREA para reduzir
cv2.imwrite(name, img, [cv2.IMWRITE_JPEG_QUALITY, 90])salva; a qualidade JPEG vai de 0 a 100 e o padrão é 95 [2]

O JPEG tem cerca de um quinto do tamanho do PNG. O JPEG descarta os detalhes a que o olho é menos sensível, e o PNG mantém todos os valores intactos. Para uma foto que vai ser compartilhada, JPEG ou WebP; para qualquer coisa que você vai medir de novo, PNG, porque um JPEG altera os números.

O recorte é uma visão (view) de fixed, e não uma cópia: mude um pixel de chart e o mesmo pixel de fixed muda. Chame .copy() quando quiser os dois independentes.

Quebre

img.shape dá (altura, largura). cv2.resize quer (largura, altura). Passe na ordem do shape e a foto sai esticada para o lado errado.

Quebre
# cv2.resize recebe (largura, altura); img.shape é (altura, largura)
h, w = fixed.shape[:2]
squashed = cv2.resize(fixed, (h // 2, w // 2))
print("asked for", (h // 2, w // 2), "got shape", squashed.shape)
cv2.imshow("width and height swapped", squashed)
Saída
asked for (319, 480) got shape (480, 319, 3)
width and height swapped
width and height swapped

Sua vez

Redimensione fixed para 320 pixels de largura, mantendo as proporções, e guarde em small.

Sua vez
small = fixed  # redimensione para 320 pixels de largura, mantendo as proporções
print(small.shape)

Por que funciona

Reduzir uma foto é reamostrá-la numa grade mais grossa, e o valor de cada pixel novo tem de ser interpolado a partir dos antigos [4]. Escolher valores sem fazer a média sobre a área que cada pixel novo cobre causa aliasing, os degraus e o moiré de Sampling: the pixel grid (em inglês). O OpenCV descreve INTER_AREA como “resampling using pixel area relation”, que “gives moire’-free results” ao reduzir [5], e INTER_LINEAR, o padrão de cv2.resize, como interpolação bilinear simples. O que o JPEG descarta, e o que isso faz com as medições, está em File formats and compression (em inglês).

Erros comuns

  • Largura e altura trocadas. A célula Quebre.
  • Editar um recorte e alterar o original. Fatias são visões; use .copy().
  • Salvar como .jpg e medir o arquivo depois. O JPEG altera os valores dos pixels; guarde um PNG de tudo que você for analisar.
  • Deixar a interpolação padrão ao reduzir muito. cv2.resize usa INTER_LINEAR por padrão, que interpola entre alguns vizinhos em vez de fazer a média da área inteira, então reduções grandes podem gerar aliasing [5].

Referências

[1] OpenCV. Geometric Transformations of Images, section “Scaling” (Python tutorial, doc/py_tutorials/py_imgproc/py_geometric_transformations/py_geometric_transformations.markdown). OpenCV 4.11.0, commit 31b0eee. github.com/opencv/opencv

[2] OpenCV. ImwriteFlags in modules/imgcodecs/include/opencv2/imgcodecs.hpp. OpenCV 4.11.0, commit 31b0eee. github.com/opencv/opencv

[3] Fairchild, M. D. (2007). The HDR Photographic Survey. IS&T 15th Color Imaging Conference, pp. 233–238. doi:10.2352/CIC.2007.15.1.art00044

[4] Gonzalez, R. C., & Woods, R. E. (2018). Digital Image Processing (4th ed.), section 2.4 “Image Sampling and Quantization”, Image Interpolation, p. 61, and section 4.5 “Extensions to Functions of Two Variables”, Aliasing in Images, p. 279. Pearson.

[5] OpenCV. InterpolationFlags and resize in modules/imgproc/include/opencv2/imgproc.hpp. OpenCV 4.11.0, commit 31b0eee. github.com/opencv/opencv