Cover Image

Fun with Frequencies:

Sharpening, Hybriding, Blending and more

1 Fun Filters

1.1 FDO: Finite Difference Operator

  • In section 1.1, we will derive and test a naive finite difference filter to perform the classic edge detection task.
  • Finite difference operator is defined as:
  • \( \mathbf{D}_x = \begin{bmatrix} 1 & -1 \end{bmatrix}, \quad \mathbf{D}_y = \begin{bmatrix} 1 \\ -1 \end{bmatrix} \)

  • Then we convolve the image first with \(\mathbf{D}_x \) obtaining all vertical edges (img: grad_x), then with \(\mathbf{D}_y\) extracting all horizontal edges (img: grad_y).
  • Then, we compute the gradient magnitude with a simple \(\sqrt{\mathbf{D}_x^2 + \mathbf{D}_y^2}\), which gives the edge image (img: grad_mag).
  • Finally, choosing a threshold value of 0.28, we take the image with pixel value higher than threshold as the edge image (img: edge_image).

  

Section 1 Image

Original: Cameraman

Shape: (542, 540, 4)

grad_x

grad_x

grad_y

grad_y

grad_mag

grad_mag

edge_image

edge_image

  

1.2 DoG: Derivative of Gaussian Filter

  • To get rid of noise, in section 2.1, we derive two ways:
  • Method 1:
    • First get a 2D Gaussian kernel using an outer product between two 1D Gaussian obtained from cv2.getGaussianKernel().
    • Then, convolve the image with the Gaussian kernel to get a blurred image.
    • Next, we compute the gradient magnitude of the blurred image using the same method as in section 1.1.
    • Finally, we choose a threshold to get the edge image.
blurred_image

blurred_image

grad_x_blurred

grad_x from blurred_image

grad_y_blurred

grad_y from blurred_image

grad_mag_blurred

grad_mag from blurred_image

edge_image

edge_image

  

  • Method 2:
    • First, we use the Gaussian to convolve with \(\mathbf{D}_x \) and \(\mathbf{D}_y \) to obtain two blurred filters.
    • Second, we convolve the original image with these two blurred filters respectively to obtain (img: grad_x_DoG) and (img: grad_y_DoG)
    • Then, we compute the gradient magnitude as in section 1.1 (img: grad_mag_DoG).
    • Finally, we choose a threshold to get the edge image (img: edge_image_DoG).

     

    DoG_x_s

    DoG_x Filter

    DoG_y_s

    DoG_y Filter

    blurred_x

    blurred_x

    grad_x_DoG

    grad_x_DoG

    grad_y_DoG

    grad_y_DoG

    grad_mag_DoG

    grad_mag_DoG

    edge_image_DoG

    edge_image_DoG

  • It's easily observable that edge_image from Method 1 looks almost identical to edge_image_DoG from Method 2, proving that convolution is indeed associative and commutative.
  •   


    2 Fun with Frequencies!

    2.1 Image "Sharpening"

    • How to sharpen an image? The idea is pretty simple in this implementation.
    • First, we blur the image using a Gaussian filter with a kernel size of 5.
    • Then, we subtract the blurred image from the original image to get the high frequency features of the image.
    • Finally, we add the high frequency features back to the original image to get the sharpened image with fake but convincing details. The intensity of the weighted high frequency image is gauged by alpha.

    Sample Image: Taj

    taj

    Original

    taj_sharpened_1

    alpha = 1

    taj_sharpened_2

    alpha = 2

    taj_sharpened_10

    alpha = 10

      

    Self Selected: Gru

    gru

    Original

    gru_sharpened_1

    alpha = 1

    gru_sharpened_4

    alpha = 4

    gru_sharpened_10

    alpha = 10

      

    Self Selected: Crease Pattern of Forest Scorpion 3.0 by Kota Imai

    cp

    Original

    cp_sharpened_1

    alpha = 1

    cp_sharpened_2

    alpha = 2

    cp_sharpened_10

    alpha = 10

    Notice the color of blue and red seems to disappear after sharpening! This is one typical drawback of this kind of sharpening, with high frequency part still being colored, the "sharpened" part actually becomes darker and darker as alpha goes up.

      

    Evaluation: Blurred and Resharpened Tomato

    tomato

    Original

    tomato_blurred

    Blurred

    tomato_sharpened_5

    Resharpened: alpha = 2

    tomato_sharpened_20

    Resharpened: alpha = 20

    Observation: most details are recovered but really detailed and good features like the fluff texture on the stem of the tomato is permenantly lost.

      

    2.2 Image Hybriding

    • How to make a hybrid image? The idea is also simple. (But the implementation is lot of hard work).
    • First, we choose img1 as the one to keep high frequency features and img2 as the one to keep low frequency features.
    • For img1, we blur it with a hand-picked kernel sigma, and keep the high frequency features by subtracting the blurred one from the original, similar to what we did in section 2.1.
    • For img2, we blur it with a hand-picked kernel sigma, and keep the low frequency directly after the low-pass filtering.
    • Here are the results:

      

    Nutrek (sample images)

    DerekPicture

    Derek Original

    nutmeg

    Nutmeg Original

    nutmeg_derek_3_5_crop

    Nutmeg_Derek (both colored)

    \(\sigma_1=3, \sigma_2=5\)

      

    Bells & Whistles: Which looks better? Colored or Gray

    nutmeg_derek_3_5

    Nutmeg: Colored

    Derek: Colored

    \(\sigma_1=3, \sigma_2=5\)

    nutmeg_derekG_7_5

    Nutmeg: Colored

    Derek: Gray

    \(\sigma_1=7, \sigma_2=5\)

    nutmegG_derek_7_5

    Nutmeg: Gray

    Derek: Colored

    \(\sigma_1=7, \sigma_2=5\)

    nutmegG_derekG_3_5

    Nutmeg: Gray

    Derek: Gray

    \(\sigma_1=3, \sigma_2=5\)

    nutmeg_derekG_21_5

    !Failure Case!

    Nutmeg: Colored

    Derek: Gray

    \(\sigma_1=21, \sigma_2=5\)

    Observation: Generally, when high freqeuncy retains only lines/textures (aka. Gray) and low frequency keeps all the blurry color, things look the best. The first line of 4 exapmles are not very intuitive but the fifth image with the colored cat (high-freq) having lapha=21 really pushes to the extreme case and surely looks bad.

      

    Elonaltman (Fav!)

    (Spoiler Alert: This are the images I will perform frequency analysis on.)
    elon

    Elon Original

    altman

    Altman Original

    elon_altman_7_5_crop

    Elon_Altman (both colored)

    \(\sigma_1=7, \sigma_2=5\)

      

    Catiger

    cat2

    Cat Original

    tiger2

    Tiger Original

    cat2G_tiger2_7_5_crop

    Cat_Tiger (Cat: Gray, Tiger: colored)

    \(\sigma_1=7, \sigma_2=5\)

    I also played around using colored Cat and colored Tiger to hybrid, which is not good looking since the color of cat actually enhanced the red-ish and yellow-ish thing. Failed images are omitted.

      

    Hamelon

    hamster

    Hamster Original

    watermelon

    Watermelon Original

    hamster_watermelon_11_13_crop

    Hamster_Watermelon (both colored)

    \(\sigma_1=11, \sigma_2=13\)

      

    Fav Set: Elonaltman Frequency Analysis

    elon_freq

    Elon Original Frequency

    elon_high_freq

    Elon High Frequency

    altman_freq

    Altman Original Frequency

    altman_low_freq

    Altman Low Frequency

    elon_altman_freq

    Elon_Altman Frequency

      

    Kiwibara: A Failure Case!

    kiwi

    Kiwi Original

    capybara

    Capybara Original

    kiwibara_1_7

    Kiwi_Capybara (both colored)

    \(\sigma_1=1, \sigma_2=7\)

    kiwibara_3_5

    Kiwi_Capybara (both colored)

    \(\sigma_1=3, \sigma_2=5\)

    The key problem with this failure is that: the high frequency image (Kiwi) doesn't really have enough textures/lines for human eyes to identify! So when hybriding these two together, people can see the capybara pretty well, but the Kiwi always looks like a stain or artifact...

      


    2.3 Gaussian and Laplacian Stacks

    • Below will first display a Gaussian Stack of Apple, then a Laplacian Stack of Apple.
    • Then, we will display a Gaussian Stack of Orange, then a Laplacian Stack of Orange.
    • Taking level 0, 1, 2, 4 for each image.
    apple_gaussian_0

    Gaussian Level: 0

    apple_gaussian_1

    Gaussian Level: 1

    apple_gaussian_2

    Gaussian Level: 2

    apple_gaussian_4

    Gaussian Level: 4

    apple_laplacian_0

    Laplacian Level: 0

    apple_laplacian_1

    Laplacian Level: 1

    apple_laplacian_2

    Laplacian Level: 2

    apple_laplacian_4

    Laplacian Level: 4

    orange_gaussian_0

    Gaussian Level: 0

    orange_gaussian_1

    Gaussian Level: 1

    orange_gaussian_2

    Gaussian Level: 2

    orange_gaussian_4

    Gaussian Level: 4

    orange_laplacian_0

    Laplacian Level: 0

    orange_laplacian_1

    Laplacian Level: 1

    orange_laplacian_2

    Laplacian Level: 2

    orange_laplacian_4

    Laplacian Level: 4

      

    • Here is the recreation of the classic figure:
    left_laplacian_scaled_masked_0

    Laplacian Level: 0

    right_laplacian_scaled_masked_0

    Laplacian Level: 0

    blended_laplacian_scaled_masked_0

    Laplacian Level: 0

    left_laplacian_scaled_masked_1

    Laplacian Level: 1

    right_laplacian_scaled_masked_1

    Laplacian Level: 1

    blended_laplacian_scaled_masked_1

    Laplacian Level: 1

    left_laplacian_scaled_masked_2

    Laplacian Level: 2

    right_laplacian_scaled_masked_2

    Laplacian Level: 2

    blended_laplacian_scaled_masked_2

    Laplacian Level: 2

    left_laplacian_scaled_masked_3

    Laplacian Level: 3

    right_laplacian_scaled_masked_3

    Laplacian Level: 3

    blended_laplacian_scaled_masked_3

    Laplacian Level: 3

    left_laplacian_scaled_masked_4

    Laplacian Level: 4

    right_laplacian_scaled_masked_4

    Laplacian Level: 4

    blended_laplacian_scaled_masked_4

    Laplacian Level: 4

    left_reconstructed

    Reconstructed

    right_reconstructed

    Reconstructed

    blended_reconstructed

    Reconstructed

      

    Addition Bells & Whistles included!!! Cheat the seaming line.

    However parameter tuning I tried, there is always a seam line that is somewhat visible. So, to overcome the isseu, I found a way to cheat a little bit by replacing the mask for level 0 laplacian stack! The noticeable seam line in the reconstructed image mainly comes from the 0-th level of the Laplacian stack because the mask on that level has a hard edge! So a very cheap way to overcome that is simply using a Gaussian blurred mask in the 0-th level and keeps blurring away! This cheating method turns out to be quite good. Check out the images below. First row is new cheated level 0 from three masked Laplacian stacks. Second row is the reconstructed. All other parameters remain the same, aka. kernel = 7, sigma = 3.

    left_laplacian_scaled_masked_0

    Laplacian Level: 0

    right_laplacian_scaled_masked_0

    Laplacian Level: 0

    blended_laplacian_scaled_masked_0

    Laplacian Level: 0

    left_reconstructed

    Reconstructed

    right_reconstructed

    Reconstructed

    blended_reconstructed

    Reconstructed

      

    2.4 Multiresolution Blending

    Nothing to say here, just interesting applications.

    BananaSage

    Alert: this is what sausage will look like when it's radioactive!

    banana_adjusted

    Banana

    sausage_adjusted

    Sausage

    bananasage_mask

    Bananasage Mask

    blended_reconstructed

    BananaSage

      

    DoplerCream (Fav!)

    Looks like another episode of Cloudy with a Chance of Meatballs has just arrived.

    dopler_adjusted

    Dopler

    icecream_adjusted

    Icecream

    doplercream_mask

    Doplercream Mask

    blended_reconstructed

    DoplerCream

      

    Huh?

    This one doesn't look good...the edges are too clear...I already used the cheating method mentioned before...

    black_adjusted

    Dude Confused meme

    butterfly_adjusted

    Is this hell? meme

    huh_mask

    The Face Mask

    blended_reconstructed

    Triple Confused

      

    Analysis of my favorite DoplerCream result

    left_laplacian_scaled_masked_0

    Laplacian Level: 0

    right_laplacian_scaled_masked_0

    Laplacian Level: 0

    blended_laplacian_scaled_masked_0

    Laplacian Level: 0

    left_laplacian_scaled_masked_1

    Laplacian Level: 1

    right_laplacian_scaled_masked_1

    Laplacian Level: 1

    blended_laplacian_scaled_masked_1

    Laplacian Level: 1

    left_laplacian_scaled_masked_2

    Laplacian Level: 2

    right_laplacian_scaled_masked_2

    Laplacian Level: 2

    blended_laplacian_scaled_masked_2

    Laplacian Level: 2

    left_laplacian_scaled_masked_3

    Laplacian Level: 3

    right_laplacian_scaled_masked_3

    Laplacian Level: 3

    blended_laplacian_scaled_masked_3

    Laplacian Level: 3

    left_laplacian_scaled_masked_4

    Laplacian Level: 4

    right_laplacian_scaled_masked_4

    Laplacian Level: 4

    blended_laplacian_scaled_masked_4

    Laplacian Level: 4

    left_reconstructed

    Reconstructed

    right_reconstructed

    Reconstructed

    blended_reconstructed

    Reconstructed