torchvision.transforms.v2.functional 모듈에서 제공하는
이미지 데이터에서 color space 와 blurring, color effect, adustment 등의 처리들에 관련된는 함수들을 소개함.
torchvision 의 다음 문서에서 color항목의 functional모듈의 함수들임.
https://docs.pytorch.org/vision/main/transforms.html#color
Transforming and augmenting images — Torchvision main documentation
Shortcuts
docs.pytorch.org
관련 gist:
https://gist.github.com/dsaint31x/d0cf8fb55ebdfa460467193edd5d5495
dl_color-torchvision-transforms-v2-functional.ipynb
dl_color-torchvision-transforms-v2-functional.ipynb - dl_color-torchvision-transforms-v2-functional.ipynb
gist.github.com
0. Prerequisites
torchvision.transforms.v2.functional 모듈은,
- 이미지 tensor 객체를 입력으로 받아
- 해당 이미지에 직접 적용할 수 있는 다양한 이미지 변환 함수들을 제공함.
제공되는 함수들은
torchvision.transfroms.v2 의 Transform 클래스들과 달리,
- 상태(state)를 가지지 않으며, 입력 텐서(이미지 등)를 인자로 직접 받아 변환된 텐서를 즉시 반환함.
- 간단하고 직접적이며, 변환을 한 번만 적용하거나 사용자 정의 변환 함수 내에서 다른 함수들을 조합할 때 유용
- 여러 변환을 순차적으로 적용하는 복잡한 파이프라인을 구축할 경우,
- 각 함수 호출마다 반복적인 인자 전달이 필요하여 다소 불편할 수 있음.
colab에서 다음의 코드들을 수행시켜서 이미지를 다운로드하고 아래의 예제 코드를 위한 import를 수행:
from torchvision.transforms.v2.functional import (
permute_channels, # 채널 순서 변경 (예: RGB → BGR)
rgb_to_grayscale, # RGB 이미지를 그레이스케일로 변환
grayscale_to_rgb, # 그레이스케일 이미지를 RGB로 변환
to_pil_image, # 텐서를 PIL 이미지로 변환
to_grayscale, # 이미지를 그레이스케일로 변환
gaussian_blur, # 가우시안 블러 적용
gaussian_noise, # 가우시안 노이즈 추가
invert, # 이미지 색상 반전
posterize, # 색상 단계 줄이기 (포스터화 효과)
solarize, # 특정 임계값 이상의 픽셀 반전
adjust_sharpness, # 이미지 선명도 조정
adjust_contrast, # 이미지 대비 조정
adjust_brightness, # 이미지 밝기 조정
adjust_saturation, # 이미지 채도 조정
adjust_hue, # 이미지 색조 조정
adjust_gamma, # 감마 보정 적용
autocontrast, # 자동 대비 조정: histogram stretching
equalize, # (채널별)히스토그램 평활화
)
img_path = "assets/astronaut.jpg"
img_url = "https://raw.githubusercontent.com/pytorch/vision/main/gallery/assets/astronaut.jpg"
lc_con_img_path= "assets/low_contrast.jgp"
lc_con_img_url = "https://raw.githubusercontent.com/dsaint31x/OpenCV_Python_Tutorial/master/images/hist_unequ.jpg"
!mkdir -p assets
!curl -o {img_path} {img_url}
from torchvision.io import decode_image
original_img = decode_image(img_path)
print(f" {type(original_img) = }\n \
{original_img.dtype = }\n \
{original_img.shape = }")
lc_original_img = decode_image(lc_con_img_path)
print(f" {type(lc_original_img) = }\n \
{lc_original_img.dtype = }\n \
{lc_original_img.shape = }")
다음은 이미지 출력을 위한 plot 함수임:
# https://github.com/pytorch/vision/tree/main/gallery/
# 위의 torchvision관련 예제들의 display를 위한 plot함수를 그대로 가져옴.
import matplotlib.pyplot as plt
import torch
from torchvision.utils import draw_bounding_boxes, draw_segmentation_masks
from torchvision import tv_tensors
from torchvision.transforms.v2 import functional as F
def plot(imgs, row_title=None, **imshow_kwargs):
if not isinstance(imgs[0], list):
# Make a 2d grid even if there's just 1 row
imgs = [imgs]
num_rows = len(imgs)
num_cols = len(imgs[0])
_, axs = plt.subplots(nrows=num_rows, ncols=num_cols, squeeze=False)
for row_idx, row in enumerate(imgs):
for col_idx, img in enumerate(row):
boxes = None
masks = None
if isinstance(img, tuple):
img, target = img
if isinstance(target, dict):
boxes = target.get("boxes")
masks = target.get("masks")
elif isinstance(target, tv_tensors.BoundingBoxes):
boxes = target
else:
raise ValueError(f"Unexpected target type: {type(target)}")
img = F.to_image(img)
if img.dtype.is_floating_point and img.min() < 0:
# Poor man's re-normalization for the colors to be OK-ish. This
# is useful for images coming out of Normalize()
img -= img.min()
img /= img.max()
img = F.to_dtype(img, torch.uint8, scale=True)
if boxes is not None:
img = draw_bounding_boxes(img, boxes, colors="yellow", width=3)
if masks is not None:
img = draw_segmentation_masks(img, masks.to(torch.bool), colors=["green"] * masks.shape[0], alpha=.65)
ax = axs[row_idx, col_idx]
ax.imshow(img.permute(1, 2, 0).numpy(), **imshow_kwargs)
ax.set(xticklabels=[], yticklabels=[], xticks=[], yticks=[])
if row_title is not None:
for row_idx in range(num_rows):
axs[row_idx, 0].set(ylabel=row_title[row_idx])
plt.tight_layout()
Channel 및 Color Space
1. permute_channels(inpt, permutation)
- 역할:
- 입력 이미지의 채널 순서를 주어진 순열에 따라 재배치.
- RGB → BGR, GRB 등 다양한 채널 순서 변환 가능.
- 사용 시점:
- OpenCV ndarray(BGR)와 PIL Image(RGB) 간 변환이 필요할 때.
- 특정 모델이 요구하는 채널 순서로 변환할 때.
- 데이터 증강의 일환으로 채널 순서를 랜덤화할 때.
- 주요 파라미터:
inpt(Tensor):- 변환할 이미지 텐서
[..., C, H, W].
permutation(List[int]): 채널 순서를 나타내는 인덱스 리스트.- 예:
[2, 1, 0]은 RGB → BGR 변환. - 길이는 채널 수와 동일해야 함.
- 예:
# RGB 이미지 생성 (Red, Green, Blue 채널이 명확히 구분되는 이미지)
rgb_image = torch.zeros(3, 100, 100, dtype=torch.uint8)
rgb_image[0, :50, :] = 255 # Red channel - 위쪽 절반
rgb_image[1, 50:, :50] = 255 # Green channel - 아래 왼쪽
rgb_image[2, 50:, 50:] = 255 # Blue channel - 아래 오른쪽
print(f"원본 RGB 이미지 형태: {rgb_image.shape}")
# 다양한 채널 순열
permutations = {
"RGB → BGR": [2, 1, 0], # Blue, Green, Red
"RGB → GRB": [1, 0, 2], # Green, Red, Blue
"RGB → BRG": [2, 0, 1], # Blue, Red, Green
"RGB → GBR": [1, 2, 0], # Green, Blue, Red
"RGB → RBG": [0, 2, 1], # Red, Blue, Green
}
results = {}
for name, perm in permutations.items():
result = F.permute_channels(rgb_image, perm)
results[name] = result
print(f"{name}: permutation={perm}, 결과 형태={result.shape}")
# Results
# 원본 RGB 이미지 형태: torch.Size([3, 100, 100])
# RGB → BGR: permutation=[2, 1, 0], 결과 형태=torch.Size([3, 100, 100])
# RGB → GRB: permutation=[1, 0, 2], 결과 형태=torch.Size([3, 100, 100])
# RGB → BRG: permutation=[2, 0, 1], 결과 형태=torch.Size([3, 100, 100])
# RGB → GBR: permutation=[1, 2, 0], 결과 형태=torch.Size([3, 100, 100])
# RGB → RBG: permutation=[0, 2, 1], 결과 형태=torch.Size([3, 100, 100])

2. rgb_to_grayscale(inpt, num_output_channels=1)
- 역할:
- RGB 이미지를 Gray Scale로 변환: YCbCr 의 Y (Luma)값으로 변환.
- ITU-R BT.601 표준 공식 사용: $Y = 0.299\times R + 0.587 \times G + 0.114 \times B$.
- 위의 식에서 Y는 Luma로 밝기에 해당함.
- 인간의 시각이 색상보다 밝기에 더 민감한 점을 이용한 YCbCr 이라는 color space의 Y를 구하는 공식을 사용.
YCbCr Color Space 참고: https://dsaint31.tistory.com/348#2-4.%20YCbCr%2C%20YUV-1-7
[DIP] Color Space or Color Model
Color Space or Color ModelColor Space(색 공간)은 "사람의 눈"이 3개의 color에 반응하는 감각세포(cone cell)를 통해 색을 인식하는 것에 기반하여 Tristimulus values (X,Y,Z)와 각각의 color를 연관시키는 방식처럼"
dsaint31.tistory.com
- 사용 시점:
- 컬러 이미지를 흑백으로 변환하여 처리 속도 향상이 필요할 때.
- 그레이스케일 기반 모델에 입력할 때.
- 메모리 사용량을 줄이고 싶을 때.
- 주요 파라미터:
inpt(Tensor): RGB 이미지[..., 3, H, W].num_output_channels(int): 출력 채널 수.1: 단일 채널 Gray Scale.3: 3채널 Gray Scale (r=g=b):- 메모리를 보다 많이 사용하나
- color image 기반으로 설계 및 훈련된 모델에 사용가능하다는 장점을 가짐.
gray_1ch = rgb_to_grayscale(
original_img,
num_output_channels=1,
)
# 결과 확인
print(f"{type(original_img) = }")
print(f"{type(gray_1ch) = }")
print(f"{original_img.shape = }")
print(f"{gray_1ch.shape = }")
# Results
# type(original_img) = <class 'torch.Tensor'>
# type(gray_1ch) = <class 'torch.Tensor'>
# original_img.shape = torch.Size([3, 512, 512])
# gray_1ch.shape = torch.Size([1, 512, 512])
# YCbCr의 Y로 변환
print(f"{original_img[:,255,255] = }")
print(f"{gray_1ch[:,255,255] = }")
r,g,b = original_img[:,255,255]
print(f"{(0.299*r + 0.587*g + 0.114* b).to(torch.uint8) = }") #YCbCr
# original_img[:,255,255] = tensor([15, 13, 14], dtype=torch.uint8)
# gray_1ch[:,255,255] = tensor([13], dtype=torch.uint8)
# (0.299*r + 0.587*g + 0.114* b).to(torch.uint8) = tensor(13, dtype=torch.uint8)

3. grayscale_to_rgb(inpt)
- 역할:
- 단일 채널 Gray Scale 이미지를 3채널 RGB로 변환.
- 각 채널에 동일한 Gray Scale 값을 복사.
- 사용 시점:
- 단 채널 이미지를 RGB 모델에 입력해야 할 때.
- 시각화 시 일관된 3채널 형태가 필요할 때.
- 주요 파라미터:
inpt(Tensor): 그레이스케일 이미지[..., 1, H, W].
rgb_from_gray = grayscale_to_rgb(
gray_1ch,
)
# 결과 확인
print(f"{type(gray_1ch) = }")
print(f"{type(rgb_from_gray) = }")
print(f"{gray_1ch.shape = }")
print(f"{rgb_from_gray.shape = }")
print("-"*10)
print(f"{gray_1ch[:,255,255] = }")
print(f"{rgb_from_gray[:,255,255] = }")
# Results
# type(gray_1ch) = <class 'torch.Tensor'>
# type(rgb_from_gray) = <class 'torch.Tensor'>
# gray_1ch.shape = torch.Size([1, 512, 512])
# rgb_from_gray.shape = torch.Size([3, 512, 512])
# ----------
# gray_1ch[:,255,255] = tensor([13], dtype=torch.uint8)
# rgb_from_gray[:,255,255] = tensor([13, 13, 13], dtype=torch.uint8)
4. to_grayscale(inpt, num_output_channels=1)
- 역할:
- PIL 이미지를 그레이스케일의 PIL 이미지로 변환.
- RGB, HSV 등 모든 PIL 모드 (=PIL이 지원하는 Color Space) 지원.
- 사용 시점:
- PIL 이미지를 직접 Gray Scale(L)로 변환할 때.
- 다양한 색공간의 이미지를 처리할 때.
- Tensor가 아닌 PIL 이미지를 다룰 때.
- 주요 파라미터:
inpt(PIL.Image): 변환할 PIL 이미지.num_output_channels(int): 출력 채널 수 (1 또는 3).- 주의: Tensor는 지원하지 않음: 때문에 TorchScript도 지원하지 않음.
pil_img = to_pil_image(original_img)
print(f"{type(pil_img) = }, {pil_img.mode}")
gray_from_pil = to_grayscale(
pil_img,
num_output_channels=1,
)
# 결과 확인
print(f"{type(pil_img) = }")
print(f"{type(gray_from_pil) = }")
print(f"{pil_img.size = }")
print(f"{gray_from_pil.size = }")
print(f"{pil_img.getbands() = }")
print(f"{gray_from_pil.getbands() = }")
# Results
# type(pil_img) = <class 'PIL.Image.Image'>, RGB
# type(pil_img) = <class 'PIL.Image.Image'>
# type(gray_from_pil) = <class 'PIL.Image.Image'>
# pil_img.size = (512, 512)
# gray_from_pil.size = (512, 512)
# pil_img.getbands() = ('R', 'G', 'B')
# gray_from_pil.getbands() = ('L',)

Blurring and Noise Addition
5. gaussian_blur(inpt, kernel_size, sigma=None)
- 역할:
- Gaussian Blurring (Gaussian Filtering)을 수행 : 대표적인 Low Pass Filter.
- 노이즈 제거, 이미지 평활화, 배경 흐림 효과 생성.
참고Gaussian Blurring: https://dsaint31.me/mkdocs_site/DIP/cv2/ch02/dip_low_pass_filter/?h=gaussian#gaussian-filter
BME
Low Pass Filter filter란 입력이미지에서 원하지 않는 값들은 걸러내고 원하는 값들을 추출하여 결과로 얻는 방법 또는 컴포넌트를 지칭. 대표적인 예로 edge 의 위치와 방향을 검출하여 Image Analysis 및
dsaint31.me
- 사용 시점:
- 이미지의 노이즈를 제거하고 싶을 때.
- Data Augmentation으로 블러 효과를 추가할 때.
- 주요 파라미터:
inpt(Tensor): 입력 이미지[..., C, H, W].kernel_size(int or List[int]): 가우시안 커널 크기.5: 5x5 정사각형 커널.[5, 7]: 5x7 직사각형 커널.
sigma(List[float], optional): 표준편차.None이면 자동 계산:- σ = 0.3 * ((kernel_size - 1) * 0.5 - 1) + 0.8 : OpenCV와 동일.
# 다양한 블러 효과
blur_configs = [
{"kernel_size": 5, "sigma": None, "name": "light blur"},
{"kernel_size": 15, "sigma": None, "name": "moderate blur"},
{"kernel_size": 31, "sigma": None, "name": "heavy blur"},
{"kernel_size": 21, "sigma": [2.0], "name": "small sigma"},
{"kernel_size": 21, "sigma": [8.0], "name": "large sigma"},
{"kernel_size": [15, 25], "sigma": [2.0, 4.0], "name": "anisotropic blur"},
]
fig, axes = plt.subplots(nrows=1, ncols=len(blur_configs)+1, figsize=(20,140))
axes[0].imshow(original_img.permute(1, 2, 0))
axes[0].set_title("Original", fontsize=12)
axes[0].axis("off")
results = {}
for idx,config in enumerate(blur_configs):
blurred = gaussian_blur(
original_img,
kernel_size=config["kernel_size"],
sigma=config["sigma"],
)
results[config["name"]] = blurred
sigma_info = config["sigma"] if config["sigma"] else "auto"
axes[idx+1].imshow(blurred.permute(1, 2, 0))
axes[idx+1].set_title(f"{config['name']} ({config['kernel_size']}, {sigma_info})", fontsize=7)
axes[idx+1].axis("off")

6. gaussian_noise(inpt, mean=0.0, sigma=0.1)
- 역할:
- 이미지에 Gaussian Noise 를 추가.
- 데이터 증강을 통한 모델 강건성 향상.
- 주의: 입력의 dtype이 float로 한정됨!
참고Gaussian Nosie:https://dsaint31.me/mkdocs_site/DIP/cv2/ch02/dip_low_pass_filter/?h=gaussian+noise#noises
BME
Low Pass Filter filter란 입력이미지에서 원하지 않는 값들은 걸러내고 원하는 값들을 추출하여 결과로 얻는 방법 또는 컴포넌트를 지칭. 대표적인 예로 edge 의 위치와 방향을 검출하여 Image Analysis 및
dsaint31.me
- 사용 시점:
- Data Augmentation으로 노이즈 저항성을 높이고 싶을 때.
- 실제 카메라 노이즈를 시뮬레이션할 때.
- overfitting(과적합) 방지를 위한 regularization(정규화) 효과가 필요할 때.
- 주요 파라미터:
inpt(Tensor): 입력 이미지[0, 1]범위.mean(float): 노이즈의 평균값 (기본값: 0.0).sigma(float): 노이즈의 표준편차 (기본값: 0.1).clip(bool): True가 기본으로 [0.0, 1.0] 범위의 결과 이미지가 되도록 clipping 수행.- 다음 예제에서
clip을 하지 않은 경우로, 범위가 negative값을 허용함. - 이는 matplotlib에서 Warning이 발생하는 원인임: api동작 확인을 위한 것이지 보통은 clip을 사용.
- 다음 예제에서
f_img = to_dtype(original_img, dtype=torch.float32, scale=True)
print(f"{f_img.max() = }, {f_img.min() = }")
# f_img = original_img # error발생. torch.uint8 지원하지 않음.
# 다양한 노이즈 레벨
noise_configs = [
{"mean": 0.0, "sigma": 0.05, "name": "light noise"},
{"mean": 0.0, "sigma": 0.1, "name": "moderate noise"},
{"mean": 0.0, "sigma": 0.2, "name": "heavy noise"},
{"mean": 0.1, "sigma": 0.1, "name": "positive bias noise"},
{"mean": -0.5, "sigma": 0.5, "name": "negative bias noise"},
]
fig, axes = plt.subplots(nrows=1, ncols=len(noise_configs)+1, figsize=(120,20))
axes[0].imshow(f_img.permute(1, 2, 0))
axes[0].set_title("Original", fontsize=12)
axes[0].axis("off")
results = {}
for idx,config in enumerate(noise_configs):
noisy = gaussian_noise(
f_img,
mean=config["mean"],
sigma=config["sigma"],
clip=False,
)
results[config["name"]] = noisy
print(f"{config['name']}: mean={config['mean']}, σ={config['sigma']}")
print(f" 결과 범위: [{noisy.min():.3f}, {noisy.max():.3f}]")
axes[idx+1].imshow(noisy.permute(1, 2, 0))
axes[idx+1].set_title(config["name"], fontsize=7)
axes[idx+1].axis("off")

Color Effects
7. invert(inpt)
- 역할:
- 이미지의 픽셀 값을 반전.
- float 이미지: 1.0 - pixel_value
- uint8 이미지: 255 - pixel_value.
- 이미지의 픽셀 값을 반전.
- 사용 시점:
- 특수한 시각적 효과가 필요할 때.
- data augmentation의 일환으로 color 변화를 줄 때.
- 네거티브 이미지 스타일 변환 시.
- 주요 파라미터:
inpt(Tensor): 반전할 이미지.
inverted = invert(original_img)

8. posterize(inpt, bits)
- 역할:
- 각 채널의 bits 수를 줄여 포스터화 효과 생성.
- 색상 단계를 줄여 만화나 포스터 같은 효과.
- 사용 시점:
- 예술적 효과나 스타일 변환이 필요할 때.
- 이미지 압축이나 색상 단순화가 필요할 때.
- Data Augmentation으로 색상 변화를 줄 때.
- 주요 파라미터:
inpt(Tensor): uint8 이미지[..., C, H, W].bits(int): 유지할 비트 수 (0-8).8: 원본 (256 색상).4: 16 색상.1: 2 색상.
bits_array = [1, 2, 4, 6, 8]
fig, axes = plt.subplots(1, len(bits_array)+1,figsize=(12,2))
posterize_results = {}
axes[0].imshow(original_img.permute(1, 2, 0))
axes[0].set_title("Original", fontsize=12)
axes[0].axis("off")
for idx, bits in enumerate(bits_array):
posterized = posterize(original_img, bits)
posterize_results[f"{bits}bit"] = posterized
unique_values = len(torch.unique(posterized))
print(f"{bits}bit: 고유한 색상 수 = {unique_values}")
axes[idx+1].imshow(posterized.permute(1, 2, 0))
axes[idx+1].set_title(f"{bits}bit", fontsize=6)
axes[idx+1].axis("off")
# Results
# 1bit: 고유한 색상 수 = 2
# 2bit: 고유한 색상 수 = 4
# 4bit: 고유한 색상 수 = 16
# 6bit: 고유한 색상 수 = 64
# 8bit: 고유한 색상 수 = 256

9. solarize(inpt, threshold)
- 역할:
- 임계값 이상의 픽셀을 반전시켜 solarization effect 생성.
- 사진의 과다 노출 효과 를 시뮬레이션.
- 사용 시점:
- 특수한 시각적 효과가 필요할 때.
- Data Augmentation으로 독특한 색상 변화를 줄 때.
- 예술적 이미지 변환 시.
- 주요 파라미터:
inpt(Tensor): 입력 이미지.threshold(floatorint): 반전 임계값.[0.0, 1.0]범위 (float 이미지).[0, 255]범위 (uint8 이미지).
f_img = to_dtype(original_img, dtype=torch.float32, scale=True)
print(f"{f_img.max() = }, {f_img.min() = }")
thresholds = [0.2, 0.5, 0.8]
fig, axes = plt.subplots(1, len(thresholds)+1,figsize=(2*(len(thresholds)+1),2))
axes[0].imshow(f_img.permute(1, 2, 0))
axes[0].set_title("Original", fontsize=12)
axes[0].axis("off")
solarize_results = {}
for idx, threshold in enumerate(thresholds):
solarized = solarize(f_img, threshold)
solarize_results[f"th_{threshold}"] = solarized
print(f"임계값 {threshold}: 결과 범위 [{solarized.min():.3f}, {solarized.max():.3f}]")
axes[idx+1].imshow(solarized.permute(1, 2, 0))
axes[idx+1].set_title(f"th_{threshold}", fontsize=6)
axes[idx+1].axis("off")
# Results
# f_img.max() = tensor(1.), f_img.min() = tensor(0.)
# 임계값 0.2: 결과 범위 [0.000, 0.800]
# 임계값 0.5: 결과 범위 [0.000, 0.498]
# 임계값 0.8: 결과 범위 [0.000, 0.796]

Image Adjustment (이미지 조정)
참고로, 구현 알고리즘이 Pillow의 ImageEnhance 모듈과 유사함:
2025.07.01 - [Python] - Pillow 사용법 - Basic 02 - Image Enhance
Pillow 사용법 - Basic 02 - Image Enhance
ImageEnhance 모듈을 통해 Image Enhancement 기능을 지원. 참고로, torchvision.transforms 의 image adjustment와 알고리즘이 유사함 api document: https://pillow.readthedocs.io/en/stable/reference/ImageEnhance.html 관련 gisthttps://gist.
ds31x.tistory.com
10. adjust_sharpness(inpt, sharpness_factor)
- 역할:
- 이미지의 sharpness(선명도)를 조정.
- 다음의 Unsharp Masking 기법을 사용하여 edge 강화.
- 입력이미지에 Gaussian Filtering(저주파 성분 추출): $I_\text{blur} = G_\sigma * I$
- unsharp mask 생성 : $M=I-I_\text{blur}$
- sharpening: $O = I - (1-s)M = sI +(1-s)I_\text{blur}$, $s$ 는 sharpness factor
- 사용 시점:
- 입력 tensor인 blurred image를 선명하게 만들 때.
- 이미지 품질 향상이 필요할 때.
- 데이터 증강으로 선명도 변화를 줄 때.
- 주요 파라미터:
inpt(Tensor): 입력 이미지.sharpness_factor(float): 선명도 조정 인수.0: 완전히 블러된 이미지.1: 원본 이미지.>1: 더 선명한 이미지.
# Sharpness 조정
blurred = gaussian_blur(
original_img,
kernel_size=9,
sigma=None,
)
sharpness_factors = [0.0, 0.5, 1.0, 1.5, 2.0]
fig, axes = plt.subplots(1, len(sharpness_factors)+1, figsize=(15, 3))
axes[0].imshow(blurred.permute(1, 2, 0))
axes[0].set_title("Original", fontsize=12)
axes[0].axis("off")
sharpness_results = {}
for idx, factor in enumerate(sharpness_factors):
adjusted = adjust_sharpness(blurred, factor)
sharpness_results[f"sharp_{factor}"] = adjusted
print(f"sharpness_factor={factor}: 범위 [{adjusted.min():.3f}, {adjusted.max():.3f}]")
axes[idx+1].imshow(adjusted.permute(1, 2, 0))
axes[idx+1].set_title(f"sharp_{factor}", fontsize=10)
axes[idx+1].axis("off")
# Results
# sharpness_factor=0.0: 범위 [0.000, 255.000]
# sharpness_factor=0.5: 범위 [0.000, 255.000]
# sharpness_factor=1.0: 범위 [0.000, 255.000]
# sharpness_factor=1.5: 범위 [0.000, 255.000]
# sharpness_factor=2.0: 범위 [0.000, 255.000]

11. adjust_contrast(inpt, contrast_factor)
- 역할:
- 이미지의 contrast(대비)를 수동으로 조정.
- $\text{output}=c(\text{input}-\mu_i)+\mu_i$
- $\mu_i$ : 입력이미지의 평균값.
- $c$ : contrast factor
- 밝은 부분과 어두운 부분 간의 차이를 증가/감소.
- 자동으로 clipping 됨.
- 이미지의 contrast(대비)를 수동으로 조정.
- 사용 시점:
- 이미지의 contrast를 세밀하게 조정하고 싶을 때.
- Data Augmentation 으로 다양한 contrast 조건을 시뮬레이션할 때.
- 특정 대비 수준이 필요한 전처리 시.
- 주요 파라미터:
inpt(Tensor): 입력 이미지.contrast_factor(float): 대비 조정 인수 $c$.0: 회색 이미지 (대비 없음).1: 원본 대비.>1: 높은 대비.
# adjust_contrast
contrast_factors = [0.2, 0.5, 1.0, 1.5, 2.0]
fig, axes = plt.subplots(1, len(contrast_factors)+1,figsize=(3*(len(contrast_factors)+1),3))
axes[0].imshow(original_img.permute(1, 2, 0))
axes[0].set_title("Original", fontsize=12)
axes[0].axis("off")
contrast_results = {}
for idx, factor in enumerate(contrast_factors):
adjusted = adjust_contrast(original_img, factor)
contrast_results[f"ct_{factor}"] = adjusted
print(f"contrast_factor={factor}: 범위 [{adjusted.min():.3f}, {adjusted.max():.3f}]")
axes[idx+1].imshow(adjusted.permute(1, 2, 0))
axes[idx+1].set_title(f"ct_{factor}", fontsize=6)
axes[idx+1].axis("off")
# Results
# contrast_factor=0.2: 범위 [91.000, 142.000]
# contrast_factor=0.5: 범위 [57.000, 184.000]
# contrast_factor=1.0: 범위 [0.000, 255.000]
# contrast_factor=1.5: 범위 [0.000, 255.000]
# contrast_factor=2.0: 범위 [0.000, 255.000]

12. adjust_brightness(inpt, brightness_factor)
- 역할:
- 이미지의 전체적인 밝기를 조정.
- 모든 픽셀에 동일한 값(
brightness_factor)을 곱하여 밝기 변경. - 자동으로 clipping 됨.
DIP에서 brightness란? https://dsaint31.tistory.com/796
[CV] Brightness vs. Intensity (+ Gamma Response Function)
1. 강도(Intensity):intensity는 픽셀(Pixel)의 photodiode 등에서 측정된 pixel에서의 빛의 양을 나타내는 (물리적인) 측정치임.이는 객관적으로 측정 가능하며, 그레이스케일(Grayscale) 이미지에서는 흔히 0에
dsaint31.tistory.com
- 사용 시점:
- 너무 어둡거나 밝은 이미지를 보정할 때.
- Data Augmentation으로 다양한 조명 조건을 시뮬레이션할 때.
- 일관된 밝기 수준이 필요할 때.
- 주요 파라미터:
inpt(Tensor): 입력 이미지.brightness_factor(float): 밝기 조정 인수.0: 완전히 검은 이미지.1: 원본 밝기.>1: 더 밝은 이미지.
# Brightness 조정
brightness_factors = [0.2, 0.5, 1.0, 1.5, 2.0]
fig, axes = plt.subplots(1, len(brightness_factors)+1, figsize=(15, 3))
axes[0].imshow(original_img.permute(1, 2, 0))
axes[0].set_title("Original", fontsize=12)
axes[0].axis("off")
brightness_results = {}
for idx, factor in enumerate(brightness_factors):
adjusted = adjust_brightness(original_img, factor)
brightness_results[f"br_{factor}"] = adjusted
print(f"brightness_factor={factor}: 범위 [{adjusted.min():.3f}, {adjusted.max():.3f}]")
axes[idx+1].imshow(adjusted.permute(1, 2, 0))
axes[idx+1].set_title(f"br_{factor}", fontsize=10)
axes[idx+1].axis("off")
# Results
# brightness_factor=0.2: 범위 [0.000, 51.000]
# brightness_factor=0.5: 범위 [0.000, 127.000]
# brightness_factor=1.0: 범위 [0.000, 255.000]
# brightness_factor=1.5: 범위 [0.000, 255.000]
# brightness_factor=2.0: 범위 [0.000, 255.000]

13. adjust_saturation(inpt, saturation_factor)
- 역할:
- 이미지의 color에서 saturation(채도)를 조정.
- RGB를 HSV로 변환 후 S 채널 (saturation) 조정.
- 보통 비율로 [0.0,1.0]의 실수값으로 표현됨.
- 채도가 높을 수록 해당 순수한 칼러임.
채도에 관한 참고자료: https://dsaint31.tistory.com/348#2-3.%20HSI%2C%20HSV%2C%20HSL-1-6
[DIP] Color Space or Color Model
Color Space or Color ModelColor Space(색 공간)은 "사람의 눈"이 3개의 color에 반응하는 감각세포(cone cell)를 통해 색을 인식하는 것에 기반하여 Tristimulus values (X,Y,Z)와 각각의 color를 연관시키는 방식처럼"
dsaint31.tistory.com
- 사용 시점:
- 색상이 너무 흐리거나 과도할 때 조정.
- Data Augmentation으로 색상 다양성을 추가할 때.
- 주요 파라미터:
inpt(Tensor): 입력 이미지[..., 3, H, W].saturation_factor(float): 채도 조정 인수.0: 완전한 흑백 이미지.1: 원본 채도.>1: 더 생생한 색상.
# Saturation 조정
saturation_factors = [0.0, 0.5, 1.0, 1.5, 2.0]
fig, axes = plt.subplots(1, len(saturation_factors)+1, figsize=(15, 3))
axes[0].imshow(original_img.permute(1, 2, 0))
axes[0].set_title("Original", fontsize=12)
axes[0].axis("off")
saturation_results = {}
for idx, factor in enumerate(saturation_factors):
adjusted = adjust_saturation(original_img, factor)
saturation_results[f"sat_{factor}"] = adjusted
print(f"saturation_factor={factor}: 범위 [{adjusted.min():.3f}, {adjusted.max():.3f}]")
axes[idx+1].imshow(adjusted.permute(1, 2, 0))
axes[idx+1].set_title(f"sat_{factor}", fontsize=10)
axes[idx+1].axis("off")
# Results
# saturation_factor=0.0: 범위 [0.000, 254.000]
# saturation_factor=0.5: 범위 [0.000, 254.000]
# saturation_factor=1.0: 범위 [0.000, 255.000]
# saturation_factor=1.5: 범위 [0.000, 255.000]
# saturation_factor=2.0: 범위 [0.000, 255.000]

14. adjust_hue(inpt, hue_factor)
- 역할:
- 이미지의 Hue(색상, 색조)를 순환적으로 이동.
- RGB를 HSV로 변환 후 HSV 색공간에서 H 채널을 조정.
- 보통 각도로 표시되지만 (360도 이동시 원래의 hue와 같음),
- torchvision에선 -0.5가 -180도에 해당함.
Hue에 대한 참고자료: https://dsaint31.tistory.com/348#2-3.%20HSI%2C%20HSV%2C%20HSL-1-6
[DIP] Color Space or Color Model
Color Space or Color ModelColor Space(색 공간)은 "사람의 눈"이 3개의 color에 반응하는 감각세포(cone cell)를 통해 색을 인식하는 것에 기반하여 Tristimulus values (X,Y,Z)와 각각의 color를 연관시키는 방식처럼"
dsaint31.tistory.com
- 사용 시점:
- Data Augmentation으로 다양한 색조 조건을 만들 때.
- 특정 색상 스타일로 변환할 때.
- 주요 파라미터:
inpt(Tensor): 입력 이미지[..., 3, H, W].hue_factor(float): Hue의 이동량으로 다음의 range에서 선택됨,[-0.5, 0.5].-0.5/0.5: 완전한 색조 반전.0: 원본 색조.
# Hue 조정
hue_factors = [-0.5, -0.25, 0.0, 0.25, 0.5]
fig, axes = plt.subplots(1, len(hue_factors)+1, figsize=(15, 3))
axes[0].imshow(original_img.permute(1, 2, 0))
axes[0].set_title("Original", fontsize=12)
axes[0].axis("off")
hue_results = {}
for idx, factor in enumerate(hue_factors):
adjusted = adjust_hue(original_img, factor)
hue_results[f"hue_{factor}"] = adjusted
print(f"hue_factor={factor}: 범위 [{adjusted.min():.3f}, {adjusted.max():.3f}]")
axes[idx+1].imshow(adjusted.permute(1, 2, 0))
axes[idx+1].set_title(f"hue_{factor}", fontsize=10)
axes[idx+1].axis("off")
# Results
# hue_factor=-0.5: 범위 [0.000, 255.000]
# hue_factor=-0.25: 범위 [0.000, 255.000]
# hue_factor=0.0: 범위 [0.000, 255.000]
# hue_factor=0.25: 범위 [0.000, 255.000]
# hue_factor=0.5: 범위 [0.000, 255.000]

15. adjust_gamma(inpt, gamma, gain=1.0)
- 역할:
- Gamma Correction(or Gamma Encoding/Decoding) 수행.
- 공식: $\text{output} = \text{gain} \times (\text{input} ^ \gamma)$.
https://dsaint31.tistory.com/794
[CV] Camera Response Function (+Gamma Correction)
https://www.youtube.com/watch?v=95DNdbxaIXECamera Response Function카메라가 실제 장면의 빛의 강도(Brightness)를 디지털 이미지 픽셀 값으로 변환하는 방식을 설명하는 함수.$p(\lambda)$ : Photon flux, $\lambda$ 는 waveleng
dsaint31.tistory.com
- 사용 시점:
- 모니터나 카메라의 감마 특성을 보정할 때.
- HDR 이미지 처리나 Tone 매핑 시.
- 주요 파라미터:
inpt(Tensor): 입력 이미지.gamma(float): 감마 값 (0 보다는 커야함).>1: 이미지가 어두워짐 (낮은 값의 범위가 보다 커지고, 높은 값의 범위는 줄어듬).<1: 이미지가 밝아짐 (낮은 값의 범위가 줄어들고, 높은 값의 범위가 증가).1: 변화 없음.
gain(float): 출력 스케일링 인수 (기본값: 1.0).
# Gamma 조정
gamma_factors = [0.5, 0.8, 1.0, 1.2, 2.0]
fig, axes = plt.subplots(1, len(gamma_factors)+1, figsize=(15, 3))
axes[0].imshow(original_img.permute(1, 2, 0))
axes[0].set_title("Original", fontsize=12)
axes[0].axis("off")
gamma_results = {}
for idx, factor in enumerate(gamma_factors):
adjusted = adjust_gamma(original_img, factor)
gamma_results[f"gamma_{factor}"] = adjusted
print(f"gamma_factor={factor}: 범위 [{adjusted.min():.3f}, {adjusted.max():.3f}]")
axes[idx+1].imshow(adjusted.permute(1, 2, 0))
axes[idx+1].set_title(f"gamma_{factor}", fontsize=10)
axes[idx+1].axis("off")
# Results
# gamma_factor=0.5: 범위 [0.000, 255.000]
# gamma_factor=0.8: 범위 [0.000, 255.000]
# gamma_factor=1.0: 범위 [0.000, 255.000]
# gamma_factor=1.2: 범위 [0.000, 255.000]
# gamma_factor=2.0: 범위 [0.000, 255.000]

Advanced Adjustment
16. autocontrast(inpt)
- 역할:
- Histogram Stretching 을 수행.
- histogram을 자동으로 확장하여 contrast를 최대화
- 이미지의 dynamic range를 전체 스펙트럼으로 확장.
https://dsaint31.tistory.com/838
[DIP] Histogram Stretching
Histogram Stretching은이미지의 contrast(명암대비) 를 개선하기 위해 : Image Enhancement히스토그램을 확장(=stretching)하는 기법임.이 기법은이미지의 밝기값(=intensity)이 전체 범위에 걸쳐 고르게 분포되지
dsaint31.tistory.com
- 사용 시점:
- contrast가 낮은 이미지의 품질을 자동으로 향상시킬 때.
- 일관된 contrast 수준이 필요할 때.
- 전처리 단계에서 이미지를 정규화할 때.
- 주요 파라미터:
inpt(Tensor): 입력 이미지.
lc_original_img = decode_image(lc_con_img_path)
# 4채널 → 3채널 변환
if lc_original_img.shape[0] == 4: # RGBA
lc_original_img = lc_original_img[:3] # RGB만 가져오기
print(f"RGBA → RGB 변환 완료: {lc_original_img.shape}")
elif lc_original_img.shape[0] == 1: # gray
test_img = grayscale_to_rgb(
lc_original_img,
)
print(f"gray → RGB 변환 완료: {test_img.shape}")
print(f"{lc_original_img.shape = }")
lc_original_img = test_img
autocontrast_result = autocontrast(lc_original_img)
print(f"autocontrast:",
f"원본 범위 [{lc_original_img.min():.3f},",
f"{lc_original_img.max():.3f}] →",
f"결과 범위 [{autocontrast_result.min():.3f},",
f"{autocontrast_result.max():.3f}]")
# Result
# autocontrast: 원본 범위 [105.000, 228.000] → 결과 범위 [0.000, 254.000]

17. equalize(inpt)
- 역할:
- Histogram Equalization 를 통해 이미지의 contrast 향상.
- 픽셀 분포를 균등하게 만들어 세부사항 강화.
- 주의: 일반적인 영상처리와 달리 color image에서 각 채널별로 histogram equalization이 수행됨.
https://dsaint31.tistory.com/837
[DIP] (Global) Histogram Equalization
Histogram Equalization에 대한 설명히스토그램 평활화(Histogram Equalization)는 이미지의 contrast(명암대비)를 개선하기 위한 기법 중 하나임: Image Enhancement일반적으로 이미지의 히스토그램이 특정 영역에
dsaint31.tistory.com
- 사용 시점:
- 어둡거나 contrast(대비)가 낮은 이미지를 개선할 때.
- 의료 영상이나 위성 이미지 처리 시.
- 이미지의 세부사항을 더 잘 보이게 하고 싶을 때.
- 주요 파라미터:
inpt(Tensor): 입력 이미지.
equalize_result = equalize(original_img)
print(f"autocontrast:",
f"원본 범위 [{lc_original_img.min():.3f},",
f"{lc_original_img.max():.3f}] →",
f"결과 범위 [{equalize_result.min():.3f},",
f"{equalize_result.max():.3f}]")
# Results
# autocontrast: 원본 범위 [105.000, 228.000] → 결과 범위 [0.000, 255.000]

'Python' 카테고리의 다른 글
| [PyTorch] Photometric-torchvision.transforms.v2 (0) | 2025.06.15 |
|---|---|
| [PyTorch] Geometric-torchvision.transforms.v2 (1) | 2025.06.15 |
| [PyTorch] Miscellanceous-Torchvision.transforms.v2.functional (0) | 2025.06.11 |
| [DL] CutMix and MixUp - Data Augmentation (0) | 2025.06.11 |
| [PyTorch] Conversion-Torchvision.transforms.v2.functional (0) | 2025.06.10 |