This is my first question here so I'm asking for understanding. I have to process hundreds of the satellites images.
I try to find contour of the area of the useful data located on the image - only the largest one.
Then I want to save the coordinates of the few points (x,y) corresponding to this contour. In simplest case, the area is a square and can be represented by 4 points, but for more complicated shapes the contour will be approximated by a little more points (preferably no more than ~ fifteen). However I am still not be able to find the areas on my images. Sometimes the area touches the edge of the image. Therefore, in this script I enlarge the pictures and add additional boundaries filled by the background color. Examples of pictures you will find here satellite1,satellite2,satellite3
As you see the images can have different background colors and in addition they contain countries borders and legend. I have tried to use Aidenhjj tips OpenCV - using cv2.approxPolyDP() correctly and prepared my script. I tried many approaches, filtering and tune parameters but still can't succeed with my data. I am asking you for help.
import numpy as np
import cv2
import matplotlib.pyplot as plt
image = cv2.imread('image1.jpg')
image = cv2.resize(image, None,fx=0.25, fy=0.25, interpolation = cv2.INTER_CUBIC)
ysize, xsize, channels = image.shape
print("Image size: {} x {}".format(xsize, ysize))
#calculate the histograms in r,g,b channels, measure background color
r, g, b = cv2.split(image)
image_data = image
histr = cv2.calcHist([r],[0],None,[256],[0,256])
for y in range(0,len(histr)):
elem = histr[y]
if elem == histr.max():
break
else:
y = none
R=y
histr = cv2.calcHist([g],[0],None,[256],[0,256])
for y in range(0,len(histr)):
elem = histr[y]
if elem == histr.max():
break
else:
y = none
G=y
histr = cv2.calcHist([b],[0],None,[256],[0,256])
for y in range(0,len(histr)):
elem = histr[y]
if elem == histr.max():
break
else:
y = none
B=y
color = (R, G, B)
#add borders around the image colorized as background. This will allow me to find closed contour around area with data.
bordersize=100
new_xsize = xsize + bordersize*2
new_ysize = ysize + bordersize*2
#image_border.show()
image_border=cv2.copyMakeBorder(image, top=bordersize, bottom=bordersize, left=bordersize, right=bordersize, borderType= cv2.BORDER_CONSTANT, value=[R,G,B] )
#ysizeb, xsizeb, channelsb = image_border.shape
# get a blank canvas for drawing contour on and convert image to grayscale
canvas = np.zeros(image_border.shape, np.uint8)
#imgc = cv2.medianBlur(img,21)
img2gray = cv2.cvtColor(image_border,cv2.COLOR_BGR2GRAY)
# filter out country borders
kernel = np.ones((5,5),np.float32)/25
img2gray = cv2.filter2D(img2gray,-1,kernel)
# threshold the image and extract contours
thresh = cv2.adaptiveThreshold(img2gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,11)
contours,hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
plt.subplot(111),plt.imshow(thresh,'gray')
plt.show()
# find the biggest area
cnt = contours[0]
max_area = cv2.contourArea(cnt)
for cont in contours:
if cv2.contourArea(cont) > max_area:
cnt = cont
max_area = cv2.contourArea(cont)
perimeter = cv2.arcLength(cnt,True)
epsilon = 0.01*cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt,epsilon,True)
hull = cv2.convexHull(cnt)
# cv2.isContourConvex(cnt)
cv2.drawContours(canvas, cnt, -1, (0, 255, 0), 3)
cv2.drawContours(canvas, approx, -1, (0, 0, 255), 3)
#cv2.drawContours(canvas, [hull], -1, (0, 0, 255), 3)
cv2.imshow("Contour", canvas)
k = cv2.waitKey(0)
if k == 27: # wait for ESC key to exit
cv2.destroyAllWindows()