contrast stretching using opencv

Preprocessing is one of the main step in any image processing task, in this post we need to get the foreground region and remove the background (because not contains information)

why retinal image analysis…?: by using just retinal images we can detect many abnormality (non invasive method) like diabetes ,neural diseases (like early stage of Alzheimer’s (https://www.youtube.com/watch?v=B9BV0v8jb2A), retinal tumor (retinoblastoma) and it also help’s a medical practitioner to diagnose more patients (think about a region where there are no big diagnostic lab’s and hospitals in such scenario a smartphone attachable fundus camera with good algorithm do the magic. It also reduces cost of medical diagnosis

It’s been a while since I have been working on some image processing based projects, one of the project which I am working on, is an algorithm to detect some kind of retinal abnormality from retinal fundus images. Most of the time I use MATLAB for image processing but now I am trying to learn and implement the same matlab code in openCV and python using numpy and other usefull library like skimage. It was much easier and fun to work with matlab because of availability of many in-built function and ease of use(every thing is in a single platform) but when I switch to opencv and python initially it was very hard for me to figure out what went wrong( during errors) and we don’t get same function as we do in MATLAB so in order to implement a same function we must have good understanding of math behind that particular function. During preprocessing I had to create a forground mask for rgb image for this project so I went through some online paper this one seemed much easier to implement it is one of my friend’s work(conference paper).

The algorithm:
  1. Read RGB image
  2. Extract green channel (it suggests there is much info in green channel)
  3. Use log transform for contrast stretching
  4. Do global thresholding
  5. Do morphological closing or opening (try which one gets good result)
  6. overlay mask over green channel
  7. done
So what exactly contrast stretching is…..?
compare these 2 image….
first one have intensities values are narrowed while in second we have stretched out the intensity level
In simple word to stretch out the dynamic range of intensities means the intensity range should well spread over entire image
or we can say to map narrow input intensity range into wider intensity range at output
Logarithmic Transformations can be used to brighten the intensities of an image (like the Gamma Transformation, where gamma < 1). More often, it is used to increase the detail (or contrast) of lower intensity values. the formula is
g = c*log(1 + double(f))
where:
c = constant
f = original image
g = transformed image
so lets code to calculate gusing contrast stretching in python and opencv.
function to get image mask
# Note: Please try to adjust g and th values to get desired mask
# you can  use circle fitting also to get mask 
"""
Created on Tue Feb 20 22:09:00 2018

@author: ash
"""
# from skimage.morphology import closing
import cv2
import numpy as np
import glob
from sklearn.cluster import KMeans
import cv2
# import os
## getting the mask from the rgb images
def preprocessing(img):
    # resizing using aspect ratio intact and finding the circle
    # reduce size retain aspect ratio intact
    # invert BGR 2 RGB
    RGB = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
    Ig = RGB[:, :, 2]
    [w,h] = np.shape(Ig)
    r=1200.0/Ig.shape[1]
    dim=(1200,int(Ig.shape[0]*r))
    rz = cv2.resize(Ig,dim,interpolation=cv2.INTER_AREA)
    #  convert in to float and get log trasform for contrast streching
    g = 0.2 * (np.log(1 + np.float32(rz)))
    # change into uint8
    cvuint = cv2.convertScaleAbs(g)
    # cvuint8.dtype
    ret, th = cv2.threshold(cvuint, 0, 255, cv2.THRESH_OTSU)
    ret1,th1 = cv2.threshold(Ig,0,255,cv2.THRESH_OTSU)
    # closeing operation
    # from skimage.morphology import disk
    # from skimage.morphology import erosion, dilation, opening, closing, white_tophat
    # selem = disk(30)
    # cls = opening(th, selem)
    # plot_comparison(orig_phantom, eroded, 'erosion')
    # in case using opencv
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (35,35))
    cls = cv2.morphologyEx(th, cv2.MORPH_OPEN, kernel)
    Im = cls*rz # the mask with resize image
    # cv2.imwrite('mynew.jpg', mask)
    return (Im,th,th1,cls,g,RGB)

path_dir = glob.glob('I:\\dataset\\diretdb\DRIONS-DB\\images\\*.jpg')
for k in path_dir:
    print('running code....',k)
    img = cv2.imread(k)
    (Im,th,th1,cls,g,RGB) = preprocessing(img)
    from matplotlib import pyplot as plt
    # plt.imshow(cls)
    # plt.show()
    # cv2.imshow('asd',cls)
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()
    # plot the data
    titles = ['Original Image', 'log_transform','mask using logT','mask without log_T ']
    images = [RGB,g,cls,th]
    for i in range(0,np.size(images)):
        print(i)
        plt.subplot(2, 3, i + 1)
        plt.imshow((images[i]),'gray')
        plt.title(titles[i])
        plt.xticks([]), plt.yticks([])
    plt.show()


fig: final output,diretdb data
conclusion:
By using these trasformation it gave me good intuition of numpy,opencv
references:
http://www.cs.uregina.ca/Links/class-info/425/Lab3/
http://scikit-image.org/docs/dev/auto_examples/xx_applications/plot_morphology.html

Comments