2

I'm creating a preprocessing in opencv python that computes the total area, infected region and percentage of region interest.

import cv2
import numpy as np           
import argparse

img1 = cv2.imread('19.jpg')
img = cv2.resize(img1, (0,0), fx=0.5, fy=0.5)
original = img.copy()
neworiginal = img.copy()

blur1 = cv2.GaussianBlur(img,(3,3),1)

newimg = np.zeros((img.shape[0], img.shape[1],3),np.uint8)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER , 10 ,1.0)
img = cv2.pyrMeanShiftFiltering(blur1, 20, 30, newimg, 0, criteria)

blur = cv2.GaussianBlur(img,(11,11),1)

kernel = np.ones((5,5),np.uint8)
canny = cv2.Canny(blur, 200, 290)
res = cv2.morphologyEx(canny,cv2.MORPH_CLOSE, kernel)
canny = cv2.cvtColor(canny,cv2.COLOR_GRAY2BGR)
cv2.imshow('Canny',res)

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower = np.array([5,25,25])
upper = np.array([70,255,255])

mask = cv2.inRange(hsv, lower, upper)

res = cv2.bitwise_and(hsv,hsv, mask= mask)
gray = cv2.cvtColor(res,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
_, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)


for i in contours:
    cnt = cv2.contourArea(i)
    #M = cv2.momens(i)
    #cx = int(M['m10']/M['m00'])
    if cnt > 1000:  
        cv2.drawContours(img, [i], 0, (0,0,255), 2)

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
_, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)
Tarea = cv2.contourArea(cnt)
cv2.imshow('img', img)

height, width, _ = canny.shape
min_x, min_y = width, height
max_x = max_y = 0
frame = canny.copy()

for contour, hier in zip(contours, hierarchy):

 (x,y,w,h) = cv2.boundingRect(contour)
            min_x, max_x = min(x, min_x), max(x+w, max_x)
            min_y, max_y = min(y, min_y), max(y+h, max_y)
            if w > 80 and h > 80:
                cv2.rectangle(frame, (x,y), (x+w,y+h), (255, 0, 0), 2)
                roi = img[y:y+h , x:x+w]
                originalroi = original[y:y+h , x:x+w]
if max_x - min_x > 0 and max_y - min_y > 0:
    cv2.rectangle(frame, (min_x, min_y), (max_x, max_y), (255, 0, 0), 2)

img = roi

imghls = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)

imghls[np.where((imghls==[30,200,2]).all(axis=2))] = [0,200,0]

huehls = imghls[:,:,0]

huehls[np.where(huehls==[0])] = [35]

#Thresholding on hue image
ret, thresh = cv2.threshold(huehls,28,255,cv2.THRESH_BINARY_INV)
cv2.imshow('thresh', thresh)


mask = cv2.bitwise_and(originalroi,originalroi,mask = thresh)

_, contours,heirarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

Infarea = 0

for x in range(len(contours)):

    cv2.drawContours(originalroi,contours[x],-1,(0,0,255),2)

    cv2.imshow('Contour masked',originalroi)

    #Calculating area of infected region
    Infarea += cv2.contourArea(contours[x])




#if Infarea > Tarea:
    #Tarea = img.shape[0]*img.shape[1]

print ('_______________________\n| Total area: ' + str(Tarea) + '   |\n|_____________________|')

#Finding the percentage of infection in the banana
print ('\n__________________________\n| Infected area: ' + str(Infarea) + ' |\n|________________________|')

try:
    per = 100 * Infarea/Tarea

except ZeroDivisionError:
    per = 0

print( '\n_________________________________________________\n| Percentage of infection region: ' + str(per) + ' |\n|_______________________________________________|')


cv2.imshow('orig',original)

enter image description here

Here's the image I've used in this particular code my problem is in getting the region of interest its not accurate result if we see in our own vision the infected area must be in 50% I think. Any idea how to get the best accuracy percentage of region interest because the result is not accurate as well.

SecretAgentMan
  • 2,856
  • 7
  • 21
  • 41
TrialAndError
  • 87
  • 1
  • 1
  • 7

1 Answers1

0

If your back ground will not be in the same color with the infected region, you can simply use color difference. I used C++ but can be converted to Python easily. Here is my approach:

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "highgui.h"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
    Mat src = imread( "/ur/image/directory/banana.jpg",CV_LOAD_IMAGE_GRAYSCALE );

    imshow( "Source", src );

    //check all pixels and change pixel values according to refrences
    for(int i=0; i<src.rows; i++)
    {
        for(int j=0;j<src.cols;j++)
        {
            if(src.at<uchar>(Point(j,i))>200)
                src.at<uchar>(Point(j,i)) = 0;
            else if(src.at<uchar>(Point(j,i))<30)
                src.at<uchar>(Point(j,i)) = 255;
            else
                src.at<uchar>(Point(j,i)) = 125;
        }
    }

    imshow( "First Process", src );

    Mat filtered_img;
    medianBlur ( src, filtered_img, 5 );

    imshow( "After Median", filtered_img );


    double deformation_counter = 0;
    double clean_counter = 0;

    //check all pixels and count them
    for(int i=0; i<src.rows; i++)
    {
        for(int j=0;j<src.cols;j++)
        {
            if(src.at<uchar>(Point(j,i))==255)
                deformation_counter++;
            if(src.at<uchar>(Point(j,i))==125)
                clean_counter++;
        }
    }

    double percentage = deformation_counter/(deformation_counter+clean_counter);

    cout<<percentage<<endl;

    waitKey(0);
    return 0;
}

Source image:

enter image description here

First change:

enter image description here

Result:

enter image description here

Yunus Temurlenk
  • 4,085
  • 4
  • 18
  • 39