Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

remove stripes / vertical streaks in remote sensing images

I have a remote sensing photo that has bright non continuous vertical streaks or stripes as in the pic below, my question is there a way to remove them using python and opencv or any other ip library? enter image description here,

like image 761
gin Avatar asked Oct 20 '25 23:10

gin


2 Answers

Here is another way, but it requires one to do Hit and Miss morphology on a grayscale image. Python/OpenCV (and Scipy and Mahouts) only allow Hit and Miss on binary images. So I use Imagemagick to do the full processing. (I tried the same in Python/OpenCV, but it failed due to that requirement). If you must use Python, then try similar processing in Python Wand, which uses Imagemagick. Or make a subprocess call from Python to Imagemagick.

  • Read the input
  • Copy the input and apply 7x1 median filter on the whole image
  • Copy the input and average the image to 1 row, then scale it back to full size. Then do 5x1 hit or miss morphology to extract the lines. Then thicken the line with morphology dilate. Then stretch the image to full dynamic range and threshold at a low value
  • Now merge the original and median filtered image using the mask
  • Save the output

Input:

enter image description here

magick remote_sense.jpg \
\( -clone 0 -statistic median 7x1 +write remote_sense_med_7x1.png \) \
\( -clone 0 -scale x1! -scale 1617x1210! +write remote_sense_scaled.png \
-morphology Hit-and-Miss '5x1:0,1,1,1,0' \
-morphology Dilate '3x1:1,1,1' \
-auto-level -threshold 10% +write remote_sense_mask.png \) \
-compose over -composite \
remote_sense_filtered.jpg

Median Filtered Image:

enter image description here

Image averaged to one row and scale back to full size:

enter image description here

Mask from Hit and Miss:

enter image description here

Filtered Result:

enter image description here

like image 197
fmw42 Avatar answered Oct 22 '25 13:10

fmw42


1 approach might be to apply an low pass filter on averaged columns to find the "bands" and remove them.

The implementation below use np.fft and np.ifft to remove frequencies. Other filters could be used here.

Warning - this sharp frequency cutoff leaves some "ringing" on the edges of the image (which can be somewhat removed by adding the average slope to it).

import cv2
img = cv2.imread("iamHP.jpg")

# Plot image
import matplotlib.pyplot as plt
plt.rcParams["figure.dpi"] = 200 # for bigger plot
plt.imshow(img)
plt.show()


import numpy as np
img_copy = np.copy(img)
mean_vals = np.mean(img, axis = 0)

def custom_filter_here(original):
    avg_slope = np.linspace(original[-1], original[0], original.shape[0])
    fft_data = np.fft.fft(original + avg_slope)
    fft_data[40:-40] = 0
    reconstructed = np.abs(np.fft.ifft(fft_data))
    return reconstructed - avg_slope

#For each channel
for i in range(mean_vals.shape[1]):
    #Stripes vs filtered
    original = mean_vals[:, i]
    reconstructed = custom_filter_here(original)
    #Plot difference
    plt.plot(original)
    plt.plot(reconstructed)
    plt.show()
    #Fix image
    for j, val in enumerate(reconstructed - original):
        img[:,j,i] = (img[:,j,i] + int(val)).astype(np.uint8)

#See the output
plt.imshow(img)
plt.show()

#See the change
change = img_copy.astype(np.float64) - img.astype(np.float64)
change -= np.min(change)
change /= np.max(change)
plt.imshow(change)
plt.show()

#save the image
cv2.imwrite("test.jpg", img)

output test.jpg

like image 33
arrmansa Avatar answered Oct 22 '25 12:10

arrmansa



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!