Using the Hough Circle Transform directly on a good thresholded image kind of works for this specific case, even though the detected circle is a little bit offset:
cv::Mat thres;
cv::threshold(gray, thres, 110, 255, cv::THRESH_BINARY);
std::vector<cv::Vec3f> circles;
cv::HoughCircles(thres, circles, cv::HOUGH_GRADIENT, 1, thres.rows/2, 20, 15);
for (size_t i = 0; i < circles.size(); i++)
{
cv::Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
cv::circle(input, center, 3, cv::Scalar(0, 255, 255), -1);
cv::circle(input, center, radius, cv::Scalar(0, 0, 255), 1);
}
⇨
⇨

On more complex cases you might have to try other threshold methods, as well as fill the internal parts (holes) of the segments to reconstruct them back to an elliptical form.
The processing pipeline illustrated below performs the following operations to improve the detection of the coin:
- Converts the input image to grayscale;
- Applies a threshold;
- Executes a morphology operation to join nearby segments;
- Fills the holes inside a segment;
- and finally, invokes
cv::HoughCircles()
to detect the circular shape.
⇨
⇨
⇨
⇨

It's possible to notice that the coin detection is a little bit more centralized with this approach. Anyway, here's the C++ sample code for that magic:
// Load input image
cv::Mat input = cv::imread("coin.jpg");
if (input.empty())
{
std::cout << "!!! Failed to open image" << std::endl;
return -1;
}
// Convert it to grayscale
cv::Mat gray;
cv::cvtColor(input, gray, cv::COLOR_BGR2GRAY);
// Threshold the grayscale image for segmentation purposes
cv::Mat thres;
cv::threshold(gray, thres, 110, 255, cv::THRESH_BINARY);
//cv::imwrite("threhsold.jpg", thres);
// Dirty trick to join nearby segments
cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(15, 15));
cv::morphologyEx(thres, thres, cv::MORPH_OPEN, element);
//cv::imwrite("morph.jpg", thres);
// Fill the holes inside the segments
fillHoles(thres);
//cv::imwrite("filled.jpg", thres);
// Apply the Hough Circle Transform to detect circles
std::vector<cv::Vec3f> circles;
cv::HoughCircles(thres, circles, cv::HOUGH_GRADIENT, 1, thres.rows/2, 20, 15);
std::cout << "* Number of detected circles: " << circles.size() << std::endl;
for (size_t i = 0; i < circles.size(); i++)
{
cv::Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
cv::circle(input, center, 3, cv::Scalar(0,255,255), -1);
cv::circle(input, center, radius, cv::Scalar(0,0,255), 1);
}
cv::imshow("Output", input);
//cv::imwrite("output.jpg", input);
cv::waitKey(0);
Helper function:
void fillHoles(cv::Mat& img)
{
if (img.channels() > 1)
{
std::cout << "fillHoles !!! Image must be single channel" << std::endl;
return;
}
cv::Mat holes = img.clone();
cv::floodFill(holes, cv::Point2i(0,0), cv::Scalar(1));
for (int i = 0; i < (img.rows * img.cols); i++)
if (holes.data[i] == 255)
img.data[i] = 0;
}