One possible approach is to first create a threshold image to get rid of some noise around the circle. You can then extract the edge of the circle using the Canny definition of the edge. Finally, findNonZero to get a list of pixel coordinates.
First I made a quick prototype with Python:
import cv2 import numpy as np img = cv2.imread('circle.png', 0) mask = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)[1] edges = cv2.Canny(mask, 20, 100) points = np.array([p[0] for p in cv2.findNonZero(edges)])
And then ported it to C ++, adding additional code to save all intermediate images and build the found pixels.
#include <opencv2/opencv.hpp> int main() { cv::Mat img(cv::imread("circle.png", 0)); cv::Mat mask; cv::threshold(img, mask, 127, 255, cv::THRESH_BINARY); cv::imwrite("circle_1.png", mask); cv::Mat edges; cv::Canny(mask, edges, 20, 100); cv::imwrite("circle_2.png", edges); std::vector<cv::Point2i> points; cv::findNonZero(edges, points); cv::Mat output(cv::Mat::zeros(edges.size(), CV_8UC3)); for (auto const& p : points) { output.at<cv::Vec3b>(p) = cv::Vec3b(127, 255, 127); } cv::imwrite("circle_3.png", output); }
Output threshold :

Canny output:

Redrawn pixels:

source share