One approach is to create a mask of the text and use that to do inpainting. In Python/OpenCV, there are two forms of inpainting: Telea and Navier-Stokes. Both produce about the same results.
Input:

import cv2
import numpy as np
# read input
img = cv2.imread('circle_text.png')
# convert to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# threshold and invert
thresh = cv2.threshold(gray, 155, 255, cv2.THRESH_BINARY)[1]
# apply morphology close
kernel = np.ones((3,3), np.uint8)
thresh = cv2.morphologyEx(thresh, cv2.MORPH_DILATE, kernel)
# get contours and filter to keep only small regions
mask = np.zeros_like(gray, dtype=np.uint8)
cntrs = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cntrs = cntrs[0] if len(cntrs) == 2 else cntrs[1]
for c in cntrs:
area = cv2.contourArea(c)
if area < 1000:
cv2.drawContours(mask,[c],0,255,-1)
# do inpainting
result1 = cv2.inpaint(img,mask,3,cv2.INPAINT_TELEA)
result2 = cv2.inpaint(img,mask,3,cv2.INPAINT_NS)
# save results
cv2.imwrite('circle_text_threshold.png', thresh)
cv2.imwrite('circle_text_mask.png', mask)
cv2.imwrite('circle_text_inpainted_telea.png', result1)
cv2.imwrite('circle_text_inpainted_ns.png', result2)
# show results
cv2.imshow('thresh',thresh)
cv2.imshow('mask',mask)
cv2.imshow('result1',result1)
cv2.imshow('result2',result2)
cv2.waitKey(0)
cv2.destroyAllWindows()
Threshold image:

Mask image:

Telea Inpainting:

Navier-Stokes Inpainting:
