Como posso afiar uma imagem no OpenCV?

122

Como posso afiar uma imagem usando o OpenCV ?

Existem muitas maneiras de suavizar ou embaçar, mas nenhuma que eu possa ver sobre a nitidez.

AruniRC
fonte

Respostas:

160

Um procedimento geral é apresentado no artigo da Wikipedia sobre mascaramento sem nitidez :

Você usa um filtro de suavização gaussiano e subtrai a versão suavizada da imagem original (de maneira ponderada, para que os valores de uma área constante permaneçam constantes).

Para obter uma versão mais nítida do frameinto image: (ambos cv::Mat)

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

Os parâmetros existem algo que você precisa ajustar para si mesmo.

Há também a nitidez da Lapônia, você deve encontrar algo sobre isso quando pesquisar no Google.

etarion
fonte
1
Existe uma maneira de replicar o resultado do Photoshop da Máscara de nitidez?
Royi 27/04
@Drazick Você está perguntando porque não pode ser replicado? O link para a Wikipedia foi fornecido acima. digital_unsharp_masking para ser específico
tilaprimera 2/14
@tilaprimera, estou perguntando porque o USM do Photoshop é diferente do USM "Clássico".
Royi
50

Você pode tentar um kernel simples e a função filter2D , por exemplo, em Python:

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

A Wikipedia tem uma boa visão geral dos kernels, com mais alguns exemplos aqui - https://en.wikipedia.org/wiki/Kernel_(image_processing)

No processamento de imagens, um núcleo, matriz de convolução ou máscara é uma matriz pequena. É usado para desfoque, nitidez, gravação, detecção de bordas e muito mais. Isso é realizado fazendo uma convolução entre um kernel e uma imagem.

Brian Burns
fonte
14

Você pode encontrar um exemplo de código sobre nitidez da imagem usando o algoritmo "máscara de nitidez" na documentação do OpenCV .

Alterar valores de sigma, threshold, amountvai dar resultados diferentes.

// 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);
sturkmen
fonte
Isso é lindo!
roosevelt
12

Você pode afiar uma imagem usando uma máscara de nitidez . Você pode encontrar mais informações sobre máscara de nitidez aqui . E aqui está uma implementação Python usando OpenCV:

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)
Soroush
fonte
esta parece ser uma versão bastante útil. você poderia adicionar um pouco mais de informação sobre os parâmetros. o tamanho e o sigma do kernel podem ser consultados no opencv, mas e quanto à quantidade e ao limite? Obrigado!
escolha
2
@choise amounté simplesmente a quantidade de nitidez. Por exemplo, um amountde 2.0 fornece uma imagem mais nítida em comparação com o valor padrão de 1.0. thresholdé o limite para a máscara de baixo contraste. Em outras palavras, os pixels cuja diferença entre a entrada e as imagens desfocadas são menores que thresholdpermanecerão inalterados.
Soroush
10

Qualquer imagem é uma coleção de sinais de várias frequências. As frequências mais altas controlam as bordas e as frequências mais baixas controlam o conteúdo da imagem. As arestas são formadas quando há uma transição nítida de um valor de pixel para outro, como 0 e 255 na célula adjacente. Obviamente, há uma mudança acentuada e, portanto, a borda e a alta frequência. Para aprimorar a imagem, essas transições podem ser aprimoradas ainda mais.

Uma maneira é envolver um kernel de filtro auto-criado com a imagem.

    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()

Existe outro método para subtrair uma versão borrada da imagem da versão brilhante. Isso ajuda a aprimorar a imagem. Mas isso deve ser feito com cautela, pois estamos apenas aumentando os valores de pixel. Imagine um valor de pixel em escala de cinza 190, que se multiplicado por um peso de 2 produz se 380, mas é aparado em 255 devido ao alcance máximo permitido de pixels. Isso é perda de informações e leva à imagem desbotada.

    addWeighted(frame, 1.5, image, -0.5, 0, image);
Ujjwal Saxena
fonte
5

Para maior clareza neste tópico, alguns pontos realmente devem ser feitos:

  1. Nitidez de imagens é um problema incorreto. Em outras palavras, o desfoque é uma operação com perdas, e voltar a partir dela geralmente não é possível.

  2. Para aprimorar as imagens únicas, é necessário adicionar restrições (suposições) sobre o tipo de imagem que você deseja e como ficou borrada. Esta é a área de estatísticas de imagem natural. As abordagens para aprimorar a nitidez mantêm essas estatísticas explícita ou implicitamente em seus algoritmos (o aprendizado profundo é o mais implicitamente codificado). A abordagem comum de ponderar alguns dos níveis de uma decomposição da pirâmide do DOG ou do Laplaciano , que é a generalização da resposta de Brian Burns, pressupõe que um desfoque gaussiano corrompeu a imagem, e como a ponderação é feita está conectada a suposições sobre o que era na imagem para começar.

  3. Outras fontes de informação podem tornar o problema mais aguçado. Essas fontes comuns de informação são o vídeo de um objeto em movimento ou a configuração de várias visualizações. A nitidez nesse cenário geralmente é chamada de super-resolução (que é um nome muito ruim para ele, mas ficou nos círculos acadêmicos). Existem métodos de super-resolução no OpenCV desde há muito tempo ... embora eles geralmente não funcionem tão bem para problemas reais, da última vez que os verifiquei. Espero que o aprendizado profundo tenha produzido alguns resultados maravilhosos aqui também. Talvez alguém publique comentários sobre o que vale a pena por aí.

Stefan Karlsson
fonte
3

Para afiar uma imagem, podemos usar o filtro (como em muitas respostas anteriores)

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

kernel /= denominator * kernel

Será o máximo quando o denominador for 1 e diminuirá conforme aumentado (2,3 ..)

O mais usado é quando o denominador é 3.

Abaixo está a implementação.

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

kernel = 1/3 * kernel

dst = cv2.filter2D(image, -1, kernel)
kaustubhd9
fonte
Algo parece estar faltando perto de "Será o máximo" .
Peter Mortensen
Sim Peter, obrigado!
kaustubhd9 23/06
-4

Tente com isto:

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

Você pode encontrar mais informações aqui .

mch
fonte
9
A questão é sobre a nitidez da imagem, e não a preservação da borda.
Michael Burdinov