Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Obtain features inside image and remove boundary

I want to detect features inside an image (retina scan). The image consists of a retina scan inside a rectangular box with black background.

I am working with Python 3.6, and I am using Canny Edge Detection to detect features inside the image. I understand that the algorithm for canny edge detection uses edge gradients to find edges. While Canny Edge Detection gives me features inside the retina scan for a proper choice of threshold values, it always keeps the circular rim between the retina scan and the black background in the output image.

In the output image, I want to have only the features inside the image (retina scan), and not the outer rim. How can I do this? I am searching for solutions which use Python. I am also open to the use of techniques other than Canny Edge Detection if they help to achieve the required task.

Below is the actual image, and the output image that I get from Canny Edge Detection.

enter image description here

Below is the circular rim that I am talking about (highlighted in red.)

enter image description here

Given below is the expected output image:

enter image description here

My code is given underneath:

import cv2
import matplotlib.pyplot as plt
from matplotlib.pyplot import imread as imread

plt.figure(1)
img_DR = cv2.imread('img.tif',0)
edges_DR = cv2.Canny(img_DR,20,40)

plt.subplot(121),plt.imshow(img_DR)
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(edges_DR,cmap = 'gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])

plt.show()

You can find the image used in this code here.

Thanks in advance.

like image 629
Siddharth Satpathy Avatar asked Jun 17 '19 03:06

Siddharth Satpathy


Video Answer


1 Answers

You could fix this in 3 steps:

1) Threshold your input image at a very low intensity, so your retina is the only foreground region. Looking at your image this should work just fine since you have no real black areas in your foreground region:

img = cv2.imread('retina.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,bin = cv2.threshold(gray,5,255,cv2.THRESH_BINARY)

enter image description here

enter image description here

2) Use erosion to remove a small margin from your foreground, you want to remove the part where your outer rim artifacts develop after you apply canny:

kernel = np.ones((5,5),np.uint8)
erosion = cv2.erode(bin,kernel,iterations = 1)

enter image description here

(visualised in red: the eroded area)

3) Use this eroded image as a binary mask on your current result image. This will remove the outer border while keeping all inner structures intact:

edges_DR = cv2.Canny(img,20,40)
result = cv2.bitwise_and(edges_DR,edges_DR,mask = erosion)

enter image description here

enter image description here

You may have to experiment with the kernel size for the erosion to remove the full border but only the border. But generally, this should produce really good and robust results. Even if the orientation or size of your scan is not consistent.

like image 89
T A Avatar answered Sep 24 '22 16:09

T A