Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing Photoshop High Pass Filter (HPF) in OpenCV

I need to implement a high-pass filter from Photoshop using OpenCV. I've read about high-pass filters in OpenCV and tried some kernels, like

[[ 0, -1, 0], 
 [-1, 4, -1],
 [ 0, -1, 0]].

However, the result isn't what I want to get, since the output image is mostly black-and-white while the output image in Photoshop is gray-ish. Here's examples: OpenCV high pass and Photoshop high pass. Also, I tried that:

blur = cv2.GaussianBlur(img,(ksize,ksize),0)
filtered = cv2.subtract(img,blur)

The result is similar to OpenCV high pass.

After that, I tried to add 127 to every pixel of the output image. Indeed, the image look gray-ish now, but still it's different from the Photoshop image.

So what am I missing? Thanks in advance.

EDIT. To Håken Lid: the code now is simply this:

import cv2
import numpy
img = cv2.imread('input.jpg')
blur = cv2.GaussianBlur(img,(31,31),0)
filtered = cv2.subtract(img, blur)
filtered = cv2.add(filtered, 127*numpy.ones(neg_frame.shape, numpy.uint8))
cv2.imwrite('output.jpg', filtered)

Here's result and original picture.

EDIT2. Yes, Håken Lid was right about truncating. I've edited the code once again:

import cv2
import numpy
img = cv2.imread('input.jpg')
blur = cv2.GaussianBlur(img,(31,31),0)
filtered = img - blur
filtered = filtered + 127*numpy.ones(neg_frame.shape, numpy.uint8)
cv2.imwrite('output.jpg', filtered)

The output result is this. Now it's more like what I wanted yet the difference is still here.

my code: my output photoshop: photoshop output

LAST EDIT. After playing with GaussianBlur kernel size, I've finally got what I want with ksize = 51. Thanks a lot for all the help! Now I'm feeling a bit dumb :P

like image 896
valed Avatar asked May 24 '18 11:05

valed


3 Answers

If you take an image with a single white pixel on a black background and apply a filter in Photoshop, you will get a convolution kernel from Photoshop.

like image 150
Alex Alex Avatar answered Oct 14 '22 20:10

Alex Alex


Without unnecessary imports and variables. More Pythonic shorter way.

import cv2


def highpass(img, sigma):
    return img - cv2.GaussianBlur(img, (0,0), sigma) + 127

img = cv2.imread('lena.png')
img = highpass(img, 3)

cv2.imshow('lena highpass', img)
cv2.waitKey(0)

enter image description here

like image 41
zoltron Avatar answered Oct 14 '22 20:10

zoltron


When you are subtracting the blurred image you need to use floating points instead of integers before you add the 127, otherwise it truncate the negative pixels. I also added an odd number checker to the kernel bit. Now it behaves like Photoshop.

import cv2
import numpy
img = cv2.imread('images/test.jpg')
size =50
if not size%2:
    size +=1
kernel = numpy.ones((size,size),numpy.float32)/(size*size)
filtered= cv2.filter2D(img,-1,kernel)
filtered = img.astype('float32') - filtered.astype('float32')
filtered = filtered + 127*numpy.ones(img.shape, numpy.uint8)
cv2.imwrite('output.jpg', filtered)
like image 27
jason mayo Avatar answered Oct 14 '22 20:10

jason mayo