16

I want to use unsharp mask on a 16 Bit Image.

The Image has 640 x 480 Pixels and is saved in a NumPy array.

I have done the following:

  • blurred the image with a Gaussian filter (three different methods)
  • then, created a mask by subtracting the blur Image form the original
  • finally, added the mask multiplied by WightFaktor to the original Image

But it doesn´t really work.

Here is the Python code:

Gaussian1 = ndimage.filters.gaussian_filter(Image,sigma=10.0)
Gaussian2 = filters.gaussian_filter(Image,sigma=10.0)
Gaussian3 = cv2.GaussianBlur(Image,(9,9),sigmaX=10.0)

Mask1 = Image - Gaussian1
UnsharpImage = Image + (WightFaktor*Mask1)
omni
  • 161
  • 1
  • 1
  • 6

2 Answers2

31

To get an unsharp image using OpenCV you need to use the addWeighted function as follows:

import cv2

image = cv2.imread("example.jpg")
gaussian_3 = cv2.GaussianBlur(image, (0, 0), 2.0)
unsharp_image = cv2.addWeighted(image, 2.0, gaussian_3, -1.0, 0)
cv2.imwrite("example_unsharp.jpg", unsharp_image)

Giving the following kind of result:

mandrill unsharp example

addWeighted() is used here as follows:

dst = cv2.addWeighted(src1, alpha, src2, beta, gamma)

Giving you the following transformation:

dst = src1*alpha + src2*beta + gamma

The strength of the effect can be altered by adjusting the alpha and beta weightings, for example: 1.5 and -0.5.

Martin Evans
  • 45,791
  • 17
  • 81
  • 97
  • 1
    That is not a Gaussian filter, that's close to a uniform filter. See [this old blog post of mine](https://www.crisluengo.net/archives/695) for an explanation. Instead, use `cv2.GaussianBlur(image, (0,0), 10.0)` to let OpenCV compute the proper size of the kernel. But a sigma of 10 is way too large for this purpose, try 1 or 2 instead. – Cris Luengo Sep 17 '20 at 15:39
  • There are good arguments [link](https://www.tandfonline.com/doi/full/10.1080/09500340.2016.1270881) that suggest the [mandrill](https://sipi.usc.edu/database/download.php?vol=misc&img=4.2.03), [peppers](https://sipi.usc.edu/database/download.php?vol=misc&img=4.2.07) might be more encouraging of diversity and respect. – EngrStudent Nov 12 '21 at 18:20
4

One could use scikit-image or PIL's unsharp mask implementation as well:

import numpy as np
import matplotlib.pylab as plt
from PIL import Image, ImageFilter
from skimage.io import imread
from skimage.filters import unsharp_mask
# with scikit-image
im = imread('images/lena.jpg')
im1 = np.copy(im).astype(np.float)
for i in range(3):
    im1[...,i] = unsharp_mask(im[...,i], radius=2, amount=2)
# with PIL
im = Image.open('images/lena.jpg')
im2 = im.filter(ImageFilter.UnsharpMask(radius=2, percent=150))
# plot
plt.figure(figsize=(20,7))
plt.subplot(131), plt.imshow(im), plt.axis('off'), plt.title('Original', size=20)
plt.subplot(132), plt.imshow(im1), plt.axis('off'), plt.title('Sharpened (skimage)', size=20)
plt.subplot(133), plt.imshow(im2), plt.axis('off'), plt.title('Sharpened (PIL)', size=20)
plt.show()

with the following output:

enter image description here

Also, adding some detailed stpes / comments on Martin Evans code with opencv-python:

import cv2

im = cv2.imread("images/lena.jpg")
im_blurred = cv2.GaussianBlur(im, (11,11), 10)
im1 = cv2.addWeighted(im, 1.0 + 3.0, im_blurred, -3.0, 0) # im1 = im + 3.0*(im - im_blurred)
plt.figure(figsize=(20,10))
plt.subplot(121),plt.imshow(cv2.cvtColor(im, cv2.COLOR_BGR2RGB)), plt.axis('off'), plt.title('Original Image', size=20)
plt.subplot(122),plt.imshow(cv2.cvtColor(im1, cv2.COLOR_BGR2RGB)), plt.axis('off'), plt.title('Sharpened Image', size=20)
plt.show()

enter image description here

Sandipan Dey
  • 21,482
  • 2
  • 51
  • 63