fbpx
Sigmoidal
  • Home
  • Pós-Graduação
  • Blog
  • Sobre Mim
  • Contato
Sem Resultado
Ver Todos Resultados
  • English
  • Home
  • Pós-Graduação
  • Blog
  • Sobre Mim
  • Contato
Sem Resultado
Ver Todos Resultados
Sigmoidal
Sem Resultado
Ver Todos Resultados

Analisando uma Tomografia 3D com Python

Carlos Melo por Carlos Melo
março 28, 2026
em Artigos, Deep Learning, Python, Tutoriais, Visão Computacional
0
12
VIEWS
Publicar no LinkedInCompartilhar no FacebookCompartilhar no Whatsapp

Um CT scan é, na sua essência, um array tridimensional onde cada voxel quantifica a atenuação de raios X em Unidades Hounsfield. Essa representação numérica padronizada é o que torna possível segmentar estruturas anatômicas, treinar redes neurais para detecção de lesões e construir pipelines reprodutíveis de análise, tudo a partir de operações sobre arrays NumPy.

Neste tutorial, você vai aprender a carregar um volume de tomografia computadorizada no Python usando SimpleITK, interpretar os metadados espaciais que conectam o array ao sistema de coordenadas do paciente e aplicar técnicas de windowing para visualizar diferentes estruturas na mesma fatia.

São as operações fundamentais que qualquer pipeline de visão computacional 3D em imagens médicas precisa dominar antes de partir para segmentação ou classificação.

💻

Código do Artigo

Acesse o código-fonte deste artigo gratuitamente.

Informe seu email para acessar o código:

✓ Seu código está pronto!

Abrir no Google Colab →

Bootcamp de Deep Learning e Visão Computacional

Quer aprender a construir um detector de câncer em tomografias 3D, do zero até o deploy? Compre agora o curso de Deep Learning e Visão Computacional 3D do Sigmoidal.

São 24 horas de aulas gravadas, disponíveis imediatamente após a compra, onde você vai construir um sistema completo de detecção de nódulos pulmonares usando PyTorch e o dataset LUNA16 (o maior benchmark público de CT de tórax), e realizar o deploy de um web app no Gradio..

Construa um projeto completo de detecção de câncer, e faça o deploy de uma aplicação web.

Você vai aprender a manipular volumes 3D com SimpleITK, converter coordenadas do paciente para índices do array, extrair crops 3D ao redor de candidatos a nódulo, treinar uma CNN 3D com data augmentation, avaliar o modelo com métricas clínicas e fazer deploy com Gradio.

Se você quer trabalhar com visão computacional 3D aplicada a problemas reais de saúde, inscreva-se no Bootcamp. O único pré-requisito é saber programar Python.

O Que é uma Tomografia 3D?

Uma tomografia computadorizada (CT scan) é um exame que produz um volume 3D do interior do corpo. O equipamento dispara raios X de múltiplos ângulos e reconstrói uma série de fatias transversais do paciente.

Na prática, cada CT scan que você vai manipular no Python é um array NumPy tridimensional. Cada posição nesse array é um voxel (o equivalente 3D de um pixel), e o valor numérico armazenado é medido em Unidades Hounsfield (HU), uma escala física padronizada:

  • Ar: −1000 HU
  • Gordura: −120 a −60 HU
  • Água: 0 HU
  • Tecido mole (músculo, órgãos): +40 a +80 HU
  • Pulmão inflado: −950 a −500 HU
  • Osso compacto: +1000 HU ou mais

Diferente de imagens comuns (onde valores de pixel são arbitrários), em um CT scan cada número tem significado físico. É essa propriedade que permite isolar estruturas anatômicas com simples operações de limiar.Visualização de um CT scan com diferentes janelas: pulmão, mediastino e osso

Carregando um CT Scan com SimpleITK

No dataset LUNA16, os CT scans são armazenados no formato MHD/RAW: um arquivo .mhd com os metadados (dimensões, espaçamento, origem) e um .raw com os voxels puros. No ecossistema médico em geral, o formato dominante é o DICOM, e em pesquisa também é comum encontrar NIfTI (.nii.gz). A biblioteca SimpleITK lê todos esses formatos e preserva as informações espaciais.

# instalar o SimpleITK
!pip install SimpleITK -q
import numpy as np
import matplotlib.pyplot as plt
import SimpleITK as sitk

O sitk.ReadImage retorna um objeto Image com os metadados. Para obter o array NumPy, basta usar sitk.GetArrayFromImage:

# carregar o CT scan
mhd_path = "data/1.3.6.1.4.1.14519.5.2.1.6279.6001.108197895896446896160048741492.mhd"
ct_sitk = sitk.ReadImage(mhd_path)
ct_array = sitk.GetArrayFromImage(ct_sitk)

Vamos inspecionar o que temos:

print(f"Shape: {ct_array.shape}")
print(f"Dtype: {ct_array.dtype}")
print(f"Dimensões: {ct_array.ndim}D")
Shape: (119, 512, 512)
Dtype: int16
Dimensões: 3D

São 119 fatias axiais, cada uma com 512 x 512 pixels. O SimpleITK retorna o array na ordem (Z, Y, X), mas os metadados (GetSpacing, GetOrigin) seguem a convenção (X, Y, Z). Essa inversão é fonte comum de bugs, então fique atento.

Metadados Espaciais: Spacing e Origin

Além dos voxels, um CT scan carrega metadados espaciais que conectam o array ao mundo físico:

spacing = ct_sitk.GetSpacing()
origin = ct_sitk.GetOrigin()

print(f"Espaçamento (x, y, z): {spacing} mm")
print(f"Origem: {origin}")
Espaçamento (x, y, z): (0.742, 0.742, 2.5) mm
Origem: (-182.5, -190.0, -313.75)

O espaçamento (spacing) diz a distância física, em milímetros, entre voxels consecutivos. Neste caso, cada pixel dentro de uma fatia mede 0.742 mm, mas a distância entre fatias é 2.5 mm. Isso significa que o volume é anisotrópico: a resolução não é uniforme em todas as direções.

A origem (origin) indica a posição do primeiro voxel no sistema de coordenadas do paciente. Ela é essencial para converter entre índices do array e coordenadas reais em milímetros.

Visualizando Fatias do Volume

A forma mais direta de visualizar um CT scan é exibir fatias individuais com matplotlib. Como cada fatia é um array 2D, basta indexar o primeiro eixo:

# exibir a primeira fatia
fatia = ct_array[0]
plt.imshow(fatia, cmap="gray")
plt.axis("off")
plt.show()
Primeira fatia do CT scan

Para ter uma visão geral do volume, podemos exibir fatias espaçadas regularmente:

# exibir 5 fatias distribuidas ao longo do volume
n_fatias = ct_array.shape[0]
indices = [0, n_fatias // 4, n_fatias // 2, 3 * n_fatias // 4, n_fatias - 1]

fig, axes = plt.subplots(1, 5, figsize=(18, 4))
for ax, idx in zip(axes, indices):
    ax.imshow(ct_array[idx], cmap="gray")
    ax.set_title(f"Fatia {idx}")
    ax.axis("off")
plt.tight_layout()
plt.show()
Cinco fatias distribuídas ao longo do volume do CT scan

As fatias extremas (0 e 118) mostram pouca anatomia. Conforme avançamos para o centro do volume, pulmões, costelas e coluna vertebral aparecem com clareza.

Windowing: Como Radiologistas Enxergam a Tomografia

Aqui está o conceito que separa quem apenas abre uma imagem médica de quem realmente entende o que está vendo.

Um CT scan tem uma faixa dinâmica enorme. Neste volume, os valores vão de −2048 a +3071 — o que corresponde a uma representação em 12 bits com offset (o valor exato depende do rescale intercept e rescale slope definidos nos metadados DICOM originais). Se você mapear todos esses valores para uma escala de cinza linear, quase todas as estruturas ficam invisíveis. A solução é o windowing (ou janelamento): você escolhe um centro (center) e uma largura (width), e todos os valores fora dessa janela são cortados.

É exatamente o que radiologistas fazem quando alternam entre “janela de pulmão”, “janela de mediastino” e “janela de osso”.

def aplicar_janela(img, center, width):
    """Aplica windowing a uma imagem de CT scan."""
    lower = center - width // 2
    upper = center + width // 2
    return np.clip(img, lower, upper)

A implementação é um simples np.clip. Note que a função retorna os valores em HU já recortados pela janela, e o imshow do Matplotlib normaliza automaticamente para a escala de cinza na exibição. Em um pipeline de produção, você normalizaria explicitamente para [0, 1] ou [0, 255] antes de alimentar um modelo. Veja o efeito na mesma fatia:

fatia_meio = ct_array[ct_array.shape[0] // 2]

janelas = {
    "Pulmao (C:-600, W:1500)": (-600, 1500),
    "Mediastino (C:40, W:400)": (40, 400),
    "Osso (C:400, W:1800)": (400, 1800),
}

fig, axes = plt.subplots(1, 3, figsize=(14, 5))
for ax, (nome, (center, width)) in zip(axes, janelas.items()):
    img = aplicar_janela(fatia_meio, center, width)
    ax.imshow(img, cmap="gray")
    ax.set_title(nome)
    ax.axis("off")
plt.tight_layout()
plt.show()
Comparação entre janelas de pulmão, mediastino e osso

A mesma fatia, três visualizações completamente diferentes:

  • Janela de pulmão (C:−600, W:1500): evidencia o parênquima pulmonar e as vias aéreas
  • Janela de mediastino (C:40, W:400): revela tecidos moles, vasos e órgãos
  • Janela de osso (C:400, W:1800): destaca a estrutura esquelética

Planos Anatômicos: Axial, Sagital e Coronal

Um CT scan 3D pode ser “fatiado” em três planos ortogonais, cada um revelando a anatomia de uma perspectiva diferente:

d, h, w = ct_array.shape

axial = ct_array[d // 2]          # fatia no meio do eixo Z
sagital = ct_array[:, :, w // 2]  # fatia no meio do eixo X
coronal = ct_array[:, h // 2, :]  # fatia no meio do eixo Y

fig, axes = plt.subplots(1, 3, figsize=(14, 5))
axes[0].imshow(axial, cmap="gray")
axes[0].set_title("Axial")
axes[1].imshow(sagital, cmap="gray")
axes[1].set_title("Sagital")
axes[2].imshow(coronal, cmap="gray")
axes[2].set_title("Coronal")
for ax in axes:
    ax.axis("off")
plt.tight_layout()
plt.show()
Planos axial, sagital e coronal do CT scan

Perceba como as vistas sagital e coronal parecem “esticadas” verticalmente. Isso não é um bug. Lembra do espaçamento anisotrópico? A distância entre fatias (2.5 mm) é 3.4x maior que a resolução dentro de cada fatia (0.742 mm). Por isso, quando recortamos nos eixos sagital ou coronal, a imagem fica distorcida. Corrigir isso exige um resampling para espaçamento isotrópico, que é tema para o próximo tutorial.

Takeaways

  • CT scans são arrays 3D com significado físico: cada voxel mede a atenuação de raios X em Unidades Hounsfield. Ar vale −1000, água vale 0, osso compacto vale +1000 ou mais.
  • Metadados espaciais importam: o espaçamento e a origem conectam o array ao mundo real em milímetros. Ignorar esses dados é fonte comum de erro.
  • Windowing é essencial para visualização: a mesma fatia revela pulmão, tecidos moles ou osso dependendo da janela aplicada. Em produção, normalize para [0, 1] após o clip.
  • Três planos anatômicos: axial, sagital e coronal permitem visualizar o volume de diferentes perspectivas. A anisotropia distorce os planos sagital e coronal quando o espaçamento entre fatias é diferente da resolução dentro de cada fatia.
CompartilharCompartilharEnviar
Post Anterior

Anthropic vs Pentágono: A Guerra da IA nos EUA

Carlos Melo

Carlos Melo

Engenheiro de Visão Computacional graduado em Ciências Aeronáuticas pela Academia da Força Aérea (AFA) e Mestre em Engenharia Aeroespacial pelo Instituto Tecnológico de Aeronáutica (ITA).

Relacionado Artigos

Artigos

Anthropic vs Pentágono: A Guerra da IA nos EUA

por Carlos Melo
março 27, 2026
Artigos

Faster R-CNN: O Paper Que Mudou a Detecção de Objetos

por Carlos Melo
março 26, 2026
Transfer Learning com PyTorch na Prática
Deep Learning

Transfer Learning com PyTorch na Prática

por Carlos Melo
março 24, 2026
Deep Learning

Grad-CAM: Visualizando o que uma Rede Neural Enxerga

por Carlos Melo
março 22, 2026
ViT Visual Transformer
Artigos

Vision Transformer (ViT): Implementação com Python

por Carlos Melo
março 18, 2026

Deixe um comentário Cancelar resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Mais Populares

  • ViT Visual Transformer

    Vision Transformer (ViT): Implementação com Python

    6 compartilhamentos
    Compartilhar 2 Tweet 2
  • ORB-SLAM 3: Tutorial Completo para Mapeamento 3D e Localização em Tempo Real

    458 compartilhamentos
    Compartilhar 183 Tweet 115
  • Introdução ao MediaPipe e Pose Estimation

    551 compartilhamentos
    Compartilhar 220 Tweet 138
  • Grad-CAM: Visualizando o que uma Rede Neural Enxerga

    4 compartilhamentos
    Compartilhar 2 Tweet 1
  • O Que é Amostragem e Quantização no Processamento de Imagens

    47 compartilhamentos
    Compartilhar 19 Tweet 12
  • Em Alta
  • Comentários
  • Mais Recente
Como Tratar Dados Ausentes com Pandas

Como Tratar Dados Ausentes com Pandas

agosto 13, 2019
Como usar o DALL-E 2 para gerar imagens a partir de textos

Como usar o DALL-E 2 para gerar imagens a partir de textos

dezembro 25, 2022
Introdução ao MediaPipe e Pose Estimation

Introdução ao MediaPipe e Pose Estimation

julho 15, 2023

ORB-SLAM 3: Tutorial Completo para Mapeamento 3D e Localização em Tempo Real

abril 10, 2023
Como Analisar Ações da Bolsa com Python

Como Analisar Ações da Bolsa com Python

15
Setembro Amarelo: Análise do Suicídio no Brasil, com Data Science

Setembro Amarelo: Análise do Suicídio no Brasil, com Data Science

13
Como Aprender Data Science?

Como Aprender Data Science?

9
Qual o Cenário de Data Science no Brasil hoje?

Qual o Cenário de Data Science no Brasil hoje?

8

Analisando uma Tomografia 3D com Python

março 28, 2026

Anthropic vs Pentágono: A Guerra da IA nos EUA

março 27, 2026

Faster R-CNN: O Paper Que Mudou a Detecção de Objetos

março 26, 2026
Transfer Learning com PyTorch na Prática

Transfer Learning com PyTorch na Prática

março 24, 2026
Instagram Youtube LinkedIn Twitter
Sigmoidal

O melhor conteúdo técnico de Data Science, com projetos práticos e exemplos do mundo real.

Seguir no Instagram

Categorias

  • Aeroespacial
  • Artigos
  • Blog
  • Carreira
  • Cursos
  • Data Science
  • Deep Learning
  • Destaques
  • Entrevistas
  • IA Generativa
  • Livros
  • Machine Learning
  • Notícias
  • Python
  • Teoria
  • Tutoriais
  • Visão Computacional
  • Youtube

Navegar por Tags

camera calibration carreira chatgpt cientista de dados cnn computer vision Cursos dados desbalanceados data science data science na prática decision tree deep learning deploy detecção de objetos gpt-3 IA generativa image formation inteligência artificial jupyter kaggle keras machine learning matplotlib mnist nft openai opencv overfitting pandas profissão python pytorch redes neurais redes neurais convolucionais regressão linear regressão logística salário sklearn tensorflow titanic tutorial visão computacional vídeo youtube árvore de decisão

© 2024 Sigmoidal - Aprenda Data Science, Visão Computacional e Python na prática.

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In

Add New Playlist

Sem Resultado
Ver Todos Resultados
  • Home
  • Pós-Graduação
  • Blog
  • Sobre Mim
  • Contato
  • English

© 2024 Sigmoidal - Aprenda Data Science, Visão Computacional e Python na prática.