강의

멘토링

로드맵

인프런 커뮤니티 질문&답변

다니님의 프로필 이미지
다니

작성한 질문수

컴퓨터 비전 이상 탐지, 개발부터 배포까지 올인원 마스터

이상치 데이터 합성 및 기본데이터셋 생성

이미지 노이즈 추가하는 코드 공유 부탁드립니다.

해결된 질문

작성

·

17

0

안녕하세요 강사님,

 

유익한 강의 공유해주셔서 정말 감사합니다.

다름이 아니라 이미지에 노이즈 추가하는 코드 공유 부탁드릴 수 있을까해서 큐앤에이 남기게되었습니다. 감사합니다.

답변 3

1

다니님의 프로필 이미지
다니
질문자

정말 감사합니다!!

0

데이비드최님의 프로필 이미지
데이비드최
지식공유자

안녕하세요~
많이 답답하셨겠네요.

필요하신 코드를 공유합니다~

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image, ImageDraw
from pathlib import Path

def load_image(file_path: Path) -> np.array:
    """
    Load an image from a given file path and convert it to a NumPy array.
    
    Args:
        file_path (Path): Path to the image file.
    
    Returns:
        np.array: The image as a NumPy array.
    """
    pil_image = Image.open(file_path)
    return np.array(pil_image)

def add_irregular_patch(noisy_image: np.array, patch_pixels: int, noise_value: int) -> np.array:
    """
    Adds an irregular, polygonal noise patch to the image.
    
    Args:
        noisy_image (np.array): The image array to modify.
        patch_pixels (int): Approximate area of the noise patch in pixels.
        noise_value (int): Noise value (255 for salt, 0 for pepper).
    
    Returns:
        np.array: The modified image with the noise patch added.
    """
    img_pil = Image.fromarray(noisy_image)
    draw = ImageDraw.Draw(img_pil)
    img_width, img_height = img_pil.size

    # Estimate an average radius from the patch area (area ≈ πr²)
    r = int(np.sqrt(patch_pixels / np.pi))
    r = max(r, 5)  # Ensure a minimum patch size

    # Choose a random center where the patch can fit
    center_x = np.random.randint(r, img_width - r)
    center_y = np.random.randint(r, img_height - r)

    # Random number of vertices for the irregular polygon
    num_points = np.random.randint(5, 10)
    angles = np.linspace(0, 2 * np.pi, num_points, endpoint=False)
    angles += np.random.uniform(0, 2 * np.pi / num_points, size=num_points)
    # Generate random radii for each vertex around the average radius
    radii = np.random.uniform(0.5 * r, 1.5 * r, size=num_points)
    
    # Create the polygon points
    points = [
        (int(center_x + radius * np.cos(angle)), int(center_y + radius * np.sin(angle)))
        for angle, radius in zip(angles, radii)
    ]
    
    # Set the fill color based on image mode
    fill_color = (noise_value, noise_value, noise_value) if img_pil.mode == 'RGB' else noise_value

    draw.polygon(points, fill=fill_color)
    return np.array(img_pil)

def random_patch_areas(total: int, num_patches: int) -> np.array:
    """
    Split the total noise area into a random distribution of patch areas that sum to total.
    
    Args:
        total (int): Total number of noisy pixels for this noise type.
        num_patches (int): Number of patches.
    
    Returns:
        np.array: Array of patch areas.
    """
    areas = np.random.rand(num_patches)
    areas = areas / areas.sum()  # Normalize so areas sum to 1
    areas = (total * areas).astype(int)
    # Adjust in case of rounding issues
    diff = total - areas.sum()
    areas[0] += diff
    return areas

def apply_random_irregular_noise(image: np.array, amount: float, salt_vs_pepper: float) -> np.array:
    """
    Applies random irregular noise patches (both salt and pepper) to an image.
    
    Args:
        image (np.array): The original image.
        amount (float): Fraction of total image pixels to be noised.
        salt_vs_pepper (float): Fraction of noise that is salt (white).
    
    Returns:
        np.array: The noisy image.
    """
    noisy = image.copy()
    total_pixels = image.shape[0] * image.shape[1]
    num_pixels = int(amount * total_pixels)
    
    # Calculate noise areas for salt and pepper
    num_salt = int(salt_vs_pepper * num_pixels)
    num_pepper = num_pixels - num_salt

    # Randomly determine number of patches (e.g., 1 to 3 patches)
    num_salt_patches = np.random.randint(1, 10)
    num_pepper_patches = np.random.randint(1, 10)

    # Split the noise area into patch areas
    salt_patch_areas = random_patch_areas(num_salt, num_salt_patches)
    pepper_patch_areas = random_patch_areas(num_pepper, num_pepper_patches)

    # Add salt noise patches
    for area in salt_patch_areas:
        noisy = add_irregular_patch(noisy, area, 255)

    # Add pepper noise patches
    for area in pepper_patch_areas:
        noisy = add_irregular_patch(noisy, area, 0)
    
    return noisy

def plot_images(original: np.array, noisy: np.array) -> None:
    """
    Plots the original and noisy images side by side.
    
    Args:
        original (np.array): The original image.
        noisy (np.array): The noisy image.
    """
    fig, axes = plt.subplots(1, 2, figsize=(10, 5))
    axes[0].imshow(original)
    axes[0].set_title("Original Image")
    axes[0].axis("off")
    
    axes[1].imshow(noisy)
    axes[1].set_title("Image with Random Irregular Noise Patches")
    axes[1].axis("off")
    
    plt.tight_layout()
    plt.show()

def main(file_path:Path, amount:float, salt_vs_pepper:float):

    # Load the image
    image = load_image(file_path)
    
    # Apply the noise
    noisy_image = apply_random_irregular_noise(image, amount, salt_vs_pepper)
    pil_image = Image.fromarray(noisy_image)
    
    # save noisy image
    output_file_path = Path('noisy_frames') / f"{file_path.stem}_noisy{file_path.suffix}"
    output_file_path.parent.mkdir(exist_ok=True)
    pil_image.save(output_file_path, format='JPEG')
    
    # Display the original and noisy images
    plot_images(image, noisy_image)

if __name__ == "__main__":
    file_path = Path('frames') / 'frame_0.jpg'
    amount = 0.01         # Fraction of image pixels to be noised
    salt_vs_pepper = 0.6  # Fraction of noise that is salt (white)

    main(file_path, amount, salt_vs_pepper)
다니님의 프로필 이미지
다니
질문자

감사합니다:)

0

안녕하세요, 인프런 AI 인턴입니다. 다니님.

이미지에 노이즈를 추가하는 코드를 요청하셨군요. 이미지 처리 과정에서 노이즈를 추가하는 기법은 모델의 일반화 능력을 향상시키는 데 도움을 줄 수 있습니다. 하지만 요청하신 코드 자료는 일반적으로 강의 내에서 직접 제공되지 않으며, 강사님께서 Q&A 게시판을 통해 필요 시 제공 가능한 자료로 이메일 요청을 받고 계신 것으로 알고 있습니다.

강사님께 코드 또는 관련 자료에 대한 요청을 이메일로 전달하시면 도움이 될 것입니다. 이미 강의 Q&A 게시판에서 비슷한 방식으로 자료를 요청하신 다른 수강생들에 대한 답변을 확인하시려면, 아래 유사한 질의에 대한 기존 답변 링크를 참조하실 수 있습니다:

이 게시물들은 코드와 데이터를 어떻게 요청할 수 있는지에 대한 가이드를 제공할 수 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

다니님의 프로필 이미지
다니

작성한 질문수

질문하기