OpenCV에서 이미지를 어떻게 선명하게 할 수 있습니까?


122

OpenCV를 사용하여 이미지를 어떻게 선명하게 할 수 있습니까?

스무딩 또는 블러 링에는 여러 가지 방법이 있지만 선명하게하는 방법은 없습니다.

답변:


160

한 가지 일반적인 절차는 언샵 마스킹대한 Wikipedia 기사에 나와 있습니다 .

가우스 스무딩 필터를 사용하고 원본 이미지에서 스무딩 된 버전을 뺍니다 (가중 방식으로 상수 영역의 값이 일정하게 유지됨).

의 날카로운 버전을 얻으려면 frame로를 image(모두 cv::Mat)

cv::GaussianBlur(frame, image, cv::Size(0, 0), 3);
cv::addWeighted(frame, 1.5, image, -0.5, 0, image);

매개 변수는 스스로 조정해야합니다.

Laplacian 선명도도 있습니다. Google에서 뭔가를 찾아야합니다.


1
Unsharp Mask의 Photoshop 결과를 복제하는 방법이 있습니까?
Royi

@Drazick 복제 할 수 없기 때문에 묻고 있습니까? 위키 백과에 대한 링크가 위에 주어졌습니다. digital_unsharp_masking 특정을 할
tilaprimera

@tilaprimera, Photoshop의 USM이 "클래식"USM과 다르기 때문에 묻습니다.
Royi

50

간단한 커널을 시도 하고예를 들어 Python에서 filter2D 함수를.

kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
im = cv2.filter2D(im, -1, kernel)

Wikipedia에는 https://en.wikipedia.org/wiki/Kernel_(image_processing)에 더 많은 예제와 함께 커널에 대한 좋은 개요가 있습니다.

이미지 처리에서 커널, 컨볼 루션 행렬 또는 마스크는 작은 행렬입니다. 블러 링, 샤프닝, 엠보싱, 가장자리 감지 등에 사용됩니다. 이것은 커널과 이미지 사이에 컨볼 루션을 수행하여 수행됩니다.


14

OpenCV Documentation 에서 "unsharp mask"알고리즘사용하여 이미지 선명 화 에 대한 샘플 코드를 찾을 수 있습니다 .

값 변경 sigma, threshold, amount다른 결과를 줄 것이다.

// sharpen image using "unsharp mask" algorithm
Mat blurred; double sigma = 1, threshold = 5, amount = 1;
GaussianBlur(img, blurred, Size(), sigma, sigma);
Mat lowContrastMask = abs(img - blurred) < threshold;
Mat sharpened = img*(1+amount) + blurred*(-amount);
img.copyTo(sharpened, lowContrastMask);

이것은 아름답다!
roosevelt

12

언샵 마스크를 사용하여 이미지를 선명하게 할 수 있습니다 . 여기에서 언샵 마스킹에 대한 자세한 정보를 찾을 수 있습니다 . 다음은 OpenCV를 사용한 Python 구현입니다.

import cv2 as cv
import numpy as np

def unsharp_mask(image, kernel_size=(5, 5), sigma=1.0, amount=1.0, threshold=0):
    """Return a sharpened version of the image, using an unsharp mask."""
    blurred = cv.GaussianBlur(image, kernel_size, sigma)
    sharpened = float(amount + 1) * image - float(amount) * blurred
    sharpened = np.maximum(sharpened, np.zeros(sharpened.shape))
    sharpened = np.minimum(sharpened, 255 * np.ones(sharpened.shape))
    sharpened = sharpened.round().astype(np.uint8)
    if threshold > 0:
        low_contrast_mask = np.absolute(image - blurred) < threshold
        np.copyto(sharpened, image, where=low_contrast_mask)
    return sharpened

def example():
    image = cv.imread('my-image.jpg')
    sharpened_image = unsharp_mask(image)
    cv.imwrite('my-sharpened-image.jpg', sharpened_image)

이것은 매우 편리한 버전 인 것 같습니다. 매개 변수에 대한 정보를 조금 더 추가해 주시겠습니까? 커널 크기와 시그마는 opencv에서 찾을 수 있지만 양과 임계 값은 어떻습니까? 감사!
choise

2
@choise amount는 단순히 선명하게하는 정도입니다. 예를 들어, amount2.0은 기본값 인 1.0에 비해 더 선명한 이미지를 제공합니다. threshold대비가 낮은 마스크의 임계 값입니다. 즉, 입력 이미지와 흐릿한 이미지의 차이가 작은 픽셀 threshold은 변경되지 않습니다.
Soroush

10

모든 이미지는 다양한 주파수의 신호 모음입니다. 높은 주파수는 가장자리를 제어하고 낮은 주파수는 이미지 내용을 제어합니다. 인접한 셀에서 한 픽셀 값에서 0 및 255와 같은 다른 픽셀 값으로 급격한 전환이있을 때 가장자리가 형성됩니다. 분명히 급격한 변화가 있고 따라서 에지와 고주파가 있습니다. 이미지를 선명하게하기 위해 이러한 전환을 더욱 향상시킬 수 있습니다.

한 가지 방법은 자체 제작 필터 커널을 이미지와 결합하는 것입니다.

    import cv2
    import numpy as np

    image = cv2.imread('images/input.jpg')
    kernel = np.array([[-1,-1,-1], 
                       [-1, 9,-1],
                       [-1,-1,-1]])
    sharpened = cv2.filter2D(image, -1, kernel) # applying the sharpening kernel to the input image & displaying it.
    cv2.imshow('Image Sharpening', sharpened)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

밝은 버전에서 흐릿한 이미지를 빼는 또 다른 방법이 있습니다. 이것은 이미지를 선명하게하는 데 도움이됩니다. 그러나 픽셀 값을 늘리는 것이므로주의해서 수행해야합니다. 가중치 2를 곱하면 380이되지만 최대 허용 픽셀 범위로 인해 255에서 트리밍되는 그레이 스케일 픽셀 값 190을 상상해보십시오. 이것은 정보 손실이며 이미지가 바래 게됩니다.

    addWeighted(frame, 1.5, image, -0.5, 0, image);

5

이 항목의 명확성을 위해 몇 가지 사항을 실제로 확인해야합니다.

  1. 이미지를 선명하게하는 것은 잘못된 문제입니다. 즉, 블러 링은 손실이있는 작업이며 일반적으로 되돌릴 수 없습니다.

  2. 단일 이미지를 선명하게하려면 원하는 이미지의 종류와 흐려지는 방법에 대한 제약 (가정)을 추가해야합니다. 이것은 자연스러운 이미지 통계 영역입니다. 선명하게하기위한 접근 방식은 이러한 통계를 알고리즘에 명시 적으로 또는 암시 적으로 유지합니다 (딥 러닝이 가장 암시 적으로 코딩 된 것임). Brian Burns 답변의 일반화 인 DOG 또는 Laplacian 피라미드 분해 의 일부 수준에 가중치를 부여하는 일반적인 접근 방식은 가우시안 블러 링이 이미지를 손상 시켰으며 가중치가 수행되는 방식이 무엇인지에 대한 가정과 연결되어 있다고 가정합니다. 시작하는 이미지에서.

  3. 다른 정보 소스는 문제를 선명하게 만들 수 있습니다. 이러한 일반적인 정보 소스는 움직이는 물체의 비디오 또는 멀티 뷰 설정입니다. 이 설정에서 선명하게하는 것은 일반적으로 초 고해상도 (매우 나쁜 이름이지만 학계에 갇혀 있음)라고합니다. OpenCV 에는 오래 전부터 초 고해상도 방법이 있습니다 .... 일반적으로 실제 문제에 대해서는 잘 작동하지 않지만 마지막으로 확인했습니다. 딥 러닝이 여기에서도 멋진 결과를 낳았을 것으로 기대합니다. 어쩌면 누군가가 가치있는 것에 대한 발언을 게시 할 것입니다.


3

이미지를 선명하게하기 위해 필터를 사용할 수 있습니다 (많은 이전 답변에서와 같이)

kernel = np.array([[-1, -1, -1],[-1, 8, -1],[-1, -1, 0]], np.float32) 

kernel /= denominator * kernel

분모가 1 일 때 가장 많고 증가할수록 감소합니다 (2.3 ..).

가장 많이 사용되는 것은 분모가 3 일 때입니다.

아래는 구현입니다.

kernel = np.array([[-1, -1, -1],[-1, 8, -1],[-1, -1, 0]], np.float32) 

kernel = 1/3 * kernel

dst = cv2.filter2D(image, -1, kernel)

"가장 많을 것입니다 " 근처에서 뭔가 누락 된 것 같습니다 .
Peter Mortensen

그래 피터, 고마워!
kaustubhd9

-4

이것을 시도하십시오 :

cv::bilateralFilter(img, 9, 75, 75);

여기에서 자세한 정보를 찾을 수 있습니다 .


9
문제는 가장자리를 부드럽게하는 것이 아니라 이미지 선명 화에 관한 것입니다.
Michael Burdinov
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.