I have a noisy gray-scale image for which I want to segment/mask the large arc spanning the image from the rest. I intend to mask the arc and all of the pixels above the arc.
To do this, I have thresholded the image to create a binary image, and used cv2.findContours() to trace the outline of the arc.
Original Image:

Image after Otsu threshold:

Threshold + Closing:

Contours of closed image:

As you can see, the closed image does not create a solid arc. Closing further causes the arc to lose it's shape. The green line is a contour of the closed image. The blue line is created with approxpolyDP() but I can't get it to work. Are there better ways to mask the arc in the image perhaps?
Here is my code:
import cv2, matplotlib
import numpy as np
import matplotlib.pyplot as plt
# read an image
img = cv2.imread('oct.png')
# get gray image and apply Gaussian blur
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5, 5), 0)
# get binary image
ret, thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# close image to "solidify" it
kernel = np.ones((3,3),np.uint8)
closing = cv2.morphologyEx(thresh,cv2.MORPH_CLOSE,kernel, iterations = 3)
# find contours
(_, contours, _) = cv2.findContours(closing, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
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)
# define main arc contour approx. and hull
perimeter = cv2.arcLength(cnt, True)
epsilon = 0.1 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True)
# hull = cv2.convexHull(cnt)
# cv2.isContourConvex(cnt)
imgcopy = np.copy(img)
cv2.drawContours(imgcopy, [cnt], -1, (0, 255, 0), 3)
cv2.drawContours(imgcopy, [approx], -1, (0, 0, 255), 3)
# plot figures
plt.figure(1)
plt.imshow(imgcopy, cmap="gray")
plt.figure(2)
plt.imshow(thresh, cmap="gray")
plt.figure(3)
plt.imshow(closing, cmap="gray")

