Finding all polygons in an image OpenCV and Python

Viewed 1129

I want to calculate the area of cultivated fields of agricultural land. For that, I want to find all polygons in the image. The process I have followed is as follow

  1. Convert image to gray.
  2. Apply bilateralFilter filter for smoothing
  3. Apply dilate function to connect lines
  4. Apply erode function to fine the lines and edges
  5. Apply canny for edge detection
  6. Find contours
  7. Find those contours which have area greater than some threshold
  8. Draw contour.

The problem is that I am not able to find all the polygons. I am missing some polygons and the test image is simplest one. The complex test image can have more missing polygons. Can anyone help me in this regard.

Code is here


import cv2
import numpy as np
from scipy import misc
from scipy.ndimage import gaussian_filter
from scipy.signal import medfilt2d
import random






image = cv2.imread('img3.jpeg')

image = cv2.bilateralFilter(image, 15, 80, 80,None)
cv2.imshow('smoth', image)
cv2.waitKey(0)  
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

  
cv2.imshow('gray', gray)
cv2.waitKey(0) 
# Find Canny edges
# edged = cv2.Canny(gray, 30, 200)
thr1=50
thr2=200


kernel = np.ones((5,5 ),np.float32)/49
# gray = cv2.filter2D(gray,-1,kernel)

# kernel = np.ones((3,3), np.uint8)

gray = cv2.dilate(gray, kernel, iterations=3)

cv2.imshow('Edged dilate', gray)
cv2.waitKey(0)

gray = cv2.erode(gray, kernel, iterations=1)

cv2.imshow('Edged erode', gray)
cv2.waitKey(0)


edged = cv2.Canny(gray, thr1, thr2)
cv2.imshow("CannyImg_"+str(thr1) + "_" + str(thr2), edged)
cv2.waitKey(0)
kernel = np.ones((3,3), np.uint8)


contours, hierarchy = cv2.findContours(edged, 
    cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)


  
print("Number of Contours found = " + str(len(contours)))


cntFound = 0
finalCnt = []
for cnt in contours :
    area = cv2.contourArea(cnt)
    print("area",area)
   
    # Shortlisting the regions based on there area.
    if area > 100: 
        # approx = cv2.approxPolyDP(cnt, 
        #                           0.009 * cv2.arcLength(cnt, True), True)
        
        approx = cv2.approxPolyDP(cnt,0.001 * cv2.arcLength(cnt, True), True)
        
        
        M = cv2.moments(cnt)
        cX = int(M["m10"] / M["m00"])
        cY = int(M["m01"] / M["m00"])
   
        # Checking if the no. of sides of the selected region is 7.
        # if(len(approx) == 7): 
        r=random.randint(0,255)
        g=random.randint(0,255)
        b=random.randint(0,255)
        cv2.drawContours(image, [approx], -1, (r, g, b), 3)
        cv2.putText(image, str(cntFound), (cX - 20, cY - 20),cv2.FONT_HERSHEY_SIMPLEX, 0.5, (r, g, b), 2)
        
        cntFound = 1 + cntFound
        finalCnt.append(cnt)

print("Total found after area threshold = ", cntFound)  
cv2.imshow('Contours', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

The test image is enter image description here

and the result is shown in the below picture enter image description here

Edit 1: After adding Otsu's thresholding the results are a little better on the test image. The results are as follow

enter image description here

But with a different image, the results become so bad. The results are shown below. The left side is the original image and the right side is the result

enter image description here

Any suggestion or opinion is welcome.

0 Answers
Related