Python: How to remove pixel annotation?

Viewed 150

I have an image file like below...

enter image description here

and I would like to remove all the annotation available in that image file. It is not clear how this must be done in Python. This is what I did;

import cv2 as cv
import numpy as np

img = cv.imread("/path/to/image/1.png")
image_contours = np.zeros((img.shape[1], img.shape[0], 1), np.uint8)

image_binary = np.zeros((img.shape[1], img.shape[0], 1), np.uint8)

for channel in range(img.shape[2]):
    ret, image_thresh = cv.threshold(img[:, :, channel], 127, 255, cv.THRESH_BINARY)    
    contours = cv.findContours(image_thresh, 1, 1)[0]   
    cv.drawContours(image_contours, contours, -1, (255,255,255), 3)

contours = cv.findContours(image_contours, cv.RETR_LIST,
                           cv.CHAIN_APPROX_SIMPLE)[0]

cv.drawContours(image_binary, [max(contours, key = cv.contourArea)],
                -1, (255, 255, 255), -1)

cv.imwrite("/path/to/save/save.png", image_binary)

I dont get the original image removed from annotation. But instead I get the one below... What I am missing?

enter image description here

1 Answers

Here is one way using masked median filtering in Python/OpenCV.

  • Read the input
  • Convert to gray
  • Threshold as mask
  • Apply morphology to the mask to dilate the white letters
  • Invert mask
  • Make mask and inverted mask 3 channel images
  • Median filter the image
  • Apply mask to median filtered image
  • Apply inverted mask to input image
  • Add the two together
  • Save results

Input:

enter image description here

import cv2
import numpy as np
import math

# read image
img = cv2.imread('xray.png')

# convert to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# threshold 
mask = cv2.threshold(gray,220,255,cv2.THRESH_BINARY)[1]

# open and then dilate mask to make white regions slightly larger
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (25,25))
mask = cv2.morphologyEx(mask, cv2.MORPH_DILATE, kernel)

# invert mask
mask_inv = 255 - mask

# make mask and inverted mask 3 channel
mask = cv2.merge([mask,mask,mask])
mask_inv = cv2.merge([mask_inv,mask_inv,mask_inv])

# median filter input image
median = cv2.medianBlur(img, 55)

# apply inverted mask to image
img_masked = cv2.bitwise_and(img, mask_inv)

# apply mask to median
median_masked = cv2.bitwise_and(median, mask)

# add together
result = cv2.add(img_masked,median_masked)

# save results
cv2.imwrite('xray_mask.png', mask)
cv2.imwrite('xray_mask_inv.png', mask_inv)
cv2.imwrite('xray_median.png', median)
cv2.imwrite('xray_masked.png', img_masked)
cv2.imwrite('xray_median_masked.png', median_masked)
cv2.imwrite('xray_removed.png', result)

cv2.imshow('gray', gray)
cv2.imshow('mask', mask)
cv2.imshow('mask_inv', mask_inv )
cv2.imshow('median', median)
cv2.imshow('img_masked', img_masked)
cv2.imshow('median_masked', median_masked)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()


Mask:

enter image description here

Inverse mask:

enter image description here

Median filtered image:

enter image description here

Masked median:

enter image description here

Inverse masked input:

enter image description here

Result:

enter image description here

Related