To get better results from Tesseract, we'll need to convert the image to a binary image - which requires first converting the current three channel (RGB/BGR) image to a single channel grayscale image, then applying thresholding to this image to convert pixels above a certain threshold to white (255) and black (0). To see this approach applied to this problem, see below:
import cv2
import pytesseract
if __name__ == "__main__":
image_path = 'photo.jpeg'
image = cv2.imread(image_path)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.adaptiveThreshold(
gray, 255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY,
21, 8
)
pipeline = cv2.hconcat([image, cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR), cv2.cvtColor(thresh, cv2.COLOR_GRAY2BGR)])
cv2.imshow("Preprocessing Pipeline [Original | Grayscale | Thresholded]", pipeline)
cv2.waitKey(0)
cv2.destroyAllWindows()
text = pytesseract.image_to_string(thresh, lang='chi_sim')
print("OCR Result:")
print(text)
The visualization code can be omitted, but it was included for clarity - the figure should look something like:

Where the left is the original image provided, the center is the image converted to grayscale, and the right image is the output from thresholding to a binary image. The output is:
OCR Result:
山 华 人 氓 典 和
居 民 身 份 证 ,
签 发 机 关
, ,
0 国 咤
国
有 效 期 限 “2007.05.14-2027.05.14
Which isn't perfect but it's extracting some of the text snippets in the image. The primary configuration in the standard transformation pipeline is through the parameters of the adaptive thresholding algorithm - a tutorial from the official OpenCV documentation detailing the parameters for this algorithm (as well as other thresholding algorithms) can be found here. Additionally, you can experiment with the thresholding parameters in the script to evaluate the impact on the final extraction.
There are other transformations that can be applied, such as blurring and morphological operations which are mentioned in the documentation from Tesseract for improving quality. For example, in the snippet above, we could apply the blur operation after converting to gray scale but before thresholding:
blur = cv2.GaussianBlur(gray, (3, 3), 0) # alternatively, a box filter can be used via cv2.blur/cv2.boxFilter
For more sophisticated use-cases (e.g; a large set of images where traditional thresholding algorithms can't properly delineate the text, or Tesseract isn't working), there are deep learning models that are available. For example, CLOVA AI has models for both text detection (identifying there is text in an image) and text recognition (parsing text in an image into strings, similar to OCR).
print(pytesseract.get_languages(config=''))to get language list (I cannot install pytesseract, sorry)config = "--tessdata-dir \"/usr/share/tesseract-ocr/5/tessdata\""in the call ofpytesseract.image_to_string(...)even this seems strange becausepytesseract.get_languages(config='')gives chi_sim