{
  "source_file": "0930",
  "source_platform": "技术平台",
  "author": "Adrian Rosebrock / PyImageSearch",
  "title_listed": "OCR with Tesseract, OpenCV, and Python",
  "keywords": "OCR,Tesseract,OpenCV",
  "domain": "图像处理",
  "content_type": "教程",
  "is_paid_flag": "否",
  "url": "https://pyimagesearch.com/2018/09/17/opencv-ocr-and-text-recognition-with-tesseract/",
  "publish_date": "2018-09",
  "corpus_stage": "预训练/SFT",
  "notes": "Tesseract OCR文本识别",
  "id": "c94e2f5ddd9d",
  "collected_at": "2026-10-02T17:24:59",
  "title": "OpenCV OCR and text recognition with Tesseract - PyImageSearch",
  "body_markdown": "Click here to download the source code to this post\nLast Updated on July 5, 2021\nIn this tutorial, you will learn how to apply OpenCV OCR (Optical Character Recognition). We will perform both (1) text\ndetection\nand (2) text\nrecognition\nusing OpenCV, Python, and Tesseract.\nA few weeks ago I showed you how to\nperform text detection using OpenCV’s EAST deep learning model\n. Using this model we were able to detect and localize the bounding box coordinates of text contained in an image.\nThe next step is to take each of these areas containing text and actually recognize and OCR the text using OpenCV and Tesseract.\nTo learn how to build your own OpenCV OCR and text recognition system,\njust keep reading!\nUpdate July 2021:\nAdded section on alternatives to Tesseract OCR, including cloud-based OCR engines and the EasyOCR Python package.\nLooking for the source code to this post?\nJump Right To The Downloads Section\nOpenCV OCR and text recognition with Tesseract\nIn order to perform OpenCV OCR text recognition, we’ll first need to install Tesseract v4 which includes a highly accurate deep learning-based model for text recognition.\nFrom there, I’ll show you how to write a Python script that:\nPerforms text\ndetection\nusing OpenCV’s EAST text detector, a highly accurate deep learning text detector used to detect text in natural scene images.\nOnce we have\ndetected\nthe text regions with OpenCV, we’ll then\nextract each of the text ROIs\nand pass them into Tesseract,\nenabling us to build an entire OpenCV OCR pipeline!\nFinally, I’ll wrap up today’s tutorial by showing you some sample results of applying text recognition with OpenCV, as well as discussing some of the limitations and drawbacks of the method.\nLet’s go ahead and get started with OpenCV OCR!\nHow to install Tesseract 4\nFigure 1:\nThe Tesseract OCR engine has been around since the 1980s. As of 2018, it now includes built-in deep learning capability making it a robust OCR tool (just keep in mind that no OCR system is perfect). Using Tesseract with OpenCV’s EAST detector makes for a great combination.\nTesseract, a highly popular OCR engine, was originally developed by Hewlett Packard in the 1980s and was then open-sourced in 2005. Google adopted the project in 2006 and has been sponsoring it ever since.\nIf you’ve read my previous post on\nUsing Tesseract OCR with Python\n, you know that Tesseract can work very well under controlled conditions…\n…but will perform quite poorly if there is a significant amount of noise or your image is not properly preprocessed and cleaned before applying Tesseract.\nJust as deep learning has impacted nearly\nevery facet\nof computer vision, the same is true for character recognition and handwriting recognition.\nDeep learning-based models have managed to obtain unprecedented text recognition accuracy, far beyond traditional feature extraction and machine learning approaches.\nIt was only a matter of time until Tesseract incorporated a deep learning model to further boost OCR accuracy — and in fact, that time has come.\nThe latest release of Tesseract (v4) supports\ndeep learning-based OCR that is\nsignificantly\nmore accurate.\nThe underlying OCR engine itself utilizes a\nLong Short-Term Memory (LSTM) network\n, a kind of\nRecurrent Neural Network (RNN)\n.\nIn the remainder of this section, you will learn how to install Tesseract v4 on your machine.\nLater in this blog post, you’ll learn how to combine OpenCV’s EAST text detection algorithm with Tesseract v4 in a\nsingle Python script\nto automatically perform OpenCV OCR.\nLet’s get started configuring your machine!\nInstall OpenCV\nTo run today’s script you’ll need OpenCV installed.\nVersion 3.4.2 or better is required.\nTo install OpenCV on your system, just\nfollow one of my OpenCV installation guides\n, ensuring that you download the correct/desired version of OpenCV and OpenCV-contrib in the process.\nInstall Tesseract 4 on Ubuntu\nThe exact commands used to install Tesseract 4 on Ubuntu will be different depending on whether you are using Ubuntu 18.04 or Ubuntu 17.04 and earlier.\nTo check your Ubuntu version you can use the\nlsb_release\ncommand:\n$ lsb_release -a\nNo LSB modules are available.\nDistributor ID:\tUbuntu\nDescription:\tUbuntu 18.04.1 LTS\nRelease:\t18.04\nCodename:\tbionic\nAs you can see, I am running Ubuntu 18.04 but you should check your Ubuntu version before continuing.\nFor Ubuntu 18.04 users, Tesseract 4 is part of the main apt-get repository, making it super easy to install Tesseract via the following command:\n$ sudo apt install tesseract-ocr\nIf you’re using Ubuntu 14, 16, or 17 though, you’ll need a few extra commands due to dependency requirements.\nThe good news is that Alexander Pozdnyakov has created an\nUbuntu PPA (Personal Package Archive) for Tesseract\n, which makes it super easy to install Tesseract 4 on older versions of Ubuntu.\nJust add the\nalex-p/tesseract-ocr\nPPA repository to your system, update your package definitions, and then install Tesseract:\n$ sudo add-apt-repository ppa:alex-p/tesseract-ocr\n$ sudo apt-get update\n$ sudo apt install tesseract-ocr\nAssuming there are no errors, you should now have Tesseract 4 installed on your machine.\nInstall Tesseract 4 on macOS\nInstalling Tesseract on macOS is straightforward provided you have\nHomebrew\n, macOS’ “unofficial” package manager, installed on your system.\nJust run the following command and Tesseract v4 will be installed on your Mac:\n$ brew install tesseract\n2020-07-21 Update:\nTesseract 5 (alpha release) is available. Currently, we recommend sticking with Tesseract 4. If you would like the latest Tesseract (as of this writing it is 5.0.0-alpha), then be sure to append the\n--HEAD\nswitch at the end of the command.\nIf you already have Tesseract installed on your Mac (if you followed my\nprevious Tesseract install tutorial\n, for example), you’ll first want to unlink the original install:\n$ brew unlink tesseract\nAnd from there you can run the install command.\nVerify your Tesseract version\nFigure 2:\nScreenshot of my system terminal where I have entered the\ntesseract -v\ncommand to query for the version. I have verified that I have Tesseract 4 installed.\nOnce you have Tesseract installed on your machine you should execute the following command to verify your Tesseract version:\n$ tesseract -v\ntesseract 4.0.0-beta.3\n leptonica-1.76.0\n  libjpeg 9c : libpng 1.6.34 : libtiff 4.0.9 : zlib 1.2.11\n Found AVX512BW\n Found AVX512F\n Found AVX2\n Found AVX\n Found SSE\nAs long as you see\ntesseract 4\nsomewhere in the output you know that you have the latest version of Tesseract installed on your system.\nInstall your Tesseract + Python bindings\nNow that we have the Tesseract binary installed, we now need to install the Tesseract + Python bindings so our Python scripts can communicate with Tesseract and perform OCR on images processed by OpenCV.\nIf you are using a Python virtual environment (which I highly recommend so you can have separate, independent Python environments) use the\nworkon\ncommand to access your virtual environment:\n$ workon cv\nIn this case, I am accessing a Python virtual environment named\ncv\n(short for “computer vision”) — you can replace\ncv\nwith whatever you have named your virtual environment.\nFrom there, we’ll use pip to install\nPillow\n, a more Python-friendly version of PIL, followed by\npytesseract\nand\nimutils\n:\n$ pip install pillow\n$ pip install pytesseract\n$ pip install imutils\nNow open up a Python shell and confirm that you can import both OpenCV and\npytesseract\n:\n$ python\nPython 3.6.5 (default, Apr  1 2018, 05:46:30) \n[GCC 7.3.0] on linux\nType \"help\", \"copyright\", \"credits\" or \"license\" for more information.\n>>> import cv2\n>>> import pytesseract\n>>> import imutils\n>>>\nCongratulations!\nIf you don’t see any import errors, your machine is now configured to perform OCR and text recognition with OpenCV\nLet’s move on to the next section (skipping the Pi instructions) where we’ll learn how to actually implement a Python script to perform OpenCV OCR.\nInstall Tesseract 4 and supporting software on Raspberry Pi and Raspbian\nNote:\nYou may skip this section if you aren’t on a Raspberry Pi.\nInevitably, I’ll be asked how to install Tesseract 4 on the Rasberry Pi.\nThe following instructions aren’t for the faint of heart — you may run into problems. They are tested, but mileage may vary on your own Raspberry Pi.\nFirst, uninstall your OpenCV bindings from system site packages:\n$ sudo rm /usr/local/lib/python3.5/site-packages/cv2.so\nHere I used the\nrm\ncommand since my\ncv2.so\nfile in\nsite-packages\nis just a sym-link. If the\ncv2.so\nbindings are your\nreal\nOpenCV bindings then you may want to move the file out of\nsite-packages\nfor safe keeping.\nNow install two QT packages on your system:\n$ sudo apt-get install libqtgui4 libqt4-test\nThen, install tesseract via\nThortex’s GitHub\n:\n$ cd ~\n$ git clone https://github.com/thortex/rpi3-tesseract\n$ cd rpi3-tesseract/release\n$ ./install_requires_related2leptonica.sh\n$ ./install_requires_related2tesseract.sh\n$ ./install_tesseract.sh\nFor whatever reason, the trained English language data file was missing from the install so I needed to download and move it into the proper directory:\n$ cd ~\n$ wget https://github.com/tesseract-ocr/tessdata/raw/master/eng.traineddata\n$ sudo mv -v eng.traineddata /usr/local/share/tessdata/\nFrom there, create a new Python virtual environment:\n$ mkvirtualenv cv_tesseract -p python3\nAnd install the necessary packages:\n$ workon cv_tesseract\n$ pip install opencv-contrib-python imutils pytesseract pillow\nYou’re done! Just keep in mind that your experience may vary.\nUnderstanding OpenCV OCR and Tesseract text recognition\nFigure 3:\nThe OpenCV OCR pipeline.\nNow that we have OpenCV and Tesseract successfully installed on our system we need to briefly review our pipeline and the associated commands.\nTo start, we’ll apply\nOpenCV’s EAST text detector\nto detect the presence of text in an image. The EAST text detector will give us the bounding box\n(x, y)\n-coordinates of text ROIs.\nWe’ll extract each of these ROIs and then pass them into Tesseract v4’s LSTM deep learning text recognition algorithm.\nThe output of the LSTM will give us our actual OCR results.\nFinally, we’ll draw the OpenCV OCR results on our output image.\nBut before we actually get to our project, let’s briefly review the Tesseract command (which will be called under the hood by the\npytesseract\nlibrary).\nWhen calling the\ntessarct\nbinary we need to supply a number of flags. The three most important ones are\n-l\n,\n--oem\n, and\n--psm\n.\nThe\n-l\nflag controls the language of the input text. We’ll be using\neng\n(English) for this example but you can see all the languages Tesseract supports\nhere\n.\nThe\n--oem\nargument, or OCR Engine Mode, controls the type of algorithm used by Tesseract.\nYou can see the available OCR Engine Modes by executing the following command:\n$ tesseract --help-oem\nOCR Engine modes:\n  0    Legacy engine only.\n  1    Neural nets LSTM engine only.\n  2    Legacy + LSTM engines.\n  3    Default, based on what is available.\nWe’ll be using\n--oem 1\nto indicate that we wish to use the deep learning LSTM engine only.\nThe final important flag,\n--psm\ncontrols the automatic Page Segmentation Mode used by Tesseract:\n$ tesseract --help-psm\nPage segmentation modes:\n  0    Orientation and script detection (OSD) only.\n  1    Automatic page segmentation with OSD.\n  2    Automatic page segmentation, but no OSD, or OCR.\n  3    Fully automatic page segmentation, but no OSD. (Default)\n  4    Assume a single column of text of variable sizes.\n  5    Assume a single uniform block of vertically aligned text.\n  6    Assume a single uniform block of text.\n  7    Treat the image as a single text line.\n  8    Treat the image as a single word.\n  9    Treat the image as a single word in a circle.\n 10    Treat the image as a single character.\n 11    Sparse text. Find as much text as possible in no particular order.\n 12    Sparse text with OSD.\n 13    Raw line. Treat the image as a single text line,\n       bypassing hacks that are Tesseract-specific.\nFor OCR’ing text ROIs I’ve found that modes\n6\nand\n7\nwork well, but if you’re OCR’ing large blocks of text then you may want to try\n3\n, the default mode.\nWhenever you find yourself obtaining incorrect OCR results I highly recommend adjusting the\n--psm\nas it can have dramatic influences on your output OCR results.\nProject structure\nBe sure to grab the zip from the\n“Downloads”\nsection of the blog post.\nFrom there unzip the file and navigate into the directory. The\ntree\ncommand allows us to see the directory structure in our terminal:\n$ tree --dirsfirst\n.\n├── images\n│   ├── example_01.jpg\n│   ├── example_02.jpg\n│   ├── example_03.jpg\n│   ├── example_04.jpg\n│   └── example_05.jpg\n├── frozen_east_text_detection.pb\n└── text_recognition.py\n\n1 directory, 7 files\nOur project contains one directory and two notable files:\nimages/\n: A directory containing six test images containing scene text. We will attempt OpenCV OCR with each of these images.\nfrozen_east_text_detection.pb\n: The EAST text detector. This CNN  is pre-trained for text detection and ready to go. I did not train this model — it is provided with OpenCV; I’ve also included it in the\n“Downloads”\nfor your convenience.\ntext_recognition.py\n: Our script for OCR — we’ll review this script line by line. The script utilizes the EAST text detector to find regions of text in the image and then takes advantage of Tesseract v4 for recognition.\nImplementing our OpenCV OCR algorithm\nWe are now ready to perform text recognition with OpenCV!\nOpen up the\ntext_recognition.py\nfile and insert the following code:\n# import the necessary packages\nfrom imutils.object_detection import non_max_suppression\nimport numpy as np\nimport pytesseract\nimport argparse\nimport cv2\nToday’s OCR script requires five imports, one of which is built into OpenCV.\nMost notably, we’ll be using\npytesseract\nand OpenCV. My\nimutils\npackage will be used for\nnon-maxima suppression\nas OpenCV’s\nNMSBoxes\nfunction doesn’t seem to be working with the Python API. I’ll also note that NumPy is a dependency for OpenCV.\nThe\nargparse\npackage is included with Python and handles command line arguments — there is nothing to install.\nNow that our imports are taken care of, let’s implement the\ndecode_predictions\nfunction:\ndef decode_predictions(scores, geometry):\n\t# grab the number of rows and columns from the scores volume, then\n\t# initialize our set of bounding box rectangles and corresponding\n\t# confidence scores\n\t(numRows, numCols) = scores.shape[2:4]\n\trects = []\n\tconfidences = []\n\n\t# loop over the number of rows\n\tfor y in range(0, numRows):\n\t\t# extract the scores (probabilities), followed by the\n\t\t# geometrical data used to derive potential bounding box\n\t\t# coordinates that surround text\n\t\tscoresData = scores[0, 0, y]\n\t\txData0 = geometry[0, 0, y]\n\t\txData1 = geometry[0, 1, y]\n\t\txData2 = geometry[0, 2, y]\n\t\txData3 = geometry[0, 3, y]\n\t\tanglesData = geometry[0, 4, y]\n\n\t\t# loop over the number of columns\n\t\tfor x in range(0, numCols):\n\t\t\t# if our score does not have sufficient probability,\n\t\t\t# ignore it\n\t\t\tif scoresData[x] < args[\"min_confidence\"]:\n\t\t\t\tcontinue\n\n\t\t\t# compute the offset factor as our resulting feature\n\t\t\t# maps will be 4x smaller than the input image\n\t\t\t(offsetX, offsetY) = (x * 4.0, y * 4.0)\n\n\t\t\t# extract the rotation angle for the prediction and\n\t\t\t# then compute the sin and cosine\n\t\t\tangle = anglesData[x]\n\t\t\tcos = np.cos(angle)\n\t\t\tsin = np.sin(angle)\n\n\t\t\t# use the geometry volume to derive the width and height\n\t\t\t# of the bounding box\n\t\t\th = xData0[x] + xData2[x]\n\t\t\tw = xData1[x] + xData3[x]\n\n\t\t\t# compute both the starting and ending (x, y)-coordinates\n\t\t\t# for the text prediction bounding box\n\t\t\tendX = int(offsetX + (cos * xData1[x]) + (sin * xData2[x]))\n\t\t\tendY = int(offsetY - (sin * xData1[x]) + (cos * xData2[x]))\n\t\t\tstartX = int(endX - w)\n\t\t\tstartY = int(endY - h)\n\n\t\t\t# add the bounding box coordinates and probability score\n\t\t\t# to our respective lists\n\t\t\trects.append((startX, startY, endX, endY))\n\t\t\tconfidences.append(scoresData[x])\n\n\t# return a tuple of the bounding boxes and associated confidences\n\treturn (rects, confidences)\nThe\ndecode_predictions\nfunction begins on\nLine 8\nand is\nexplained in detail inside the EAST text detection post\n. The function:\nUses a deep learning-based text detector to\ndetect\n(not recognize) regions of text in an image.\nThe text detector produces two arrays, one containing the\nprobability\nof a given area containing text, and another that maps the score to a\nbounding box location\nin the input image.\nAs we’ll see in our OpenCV OCR pipeline, the EAST text detector model will produce two variables:\nscores\n: Probabilities for positive text regions.\ngeometry\n: The bounding boxes of the text regions.\n…each of which is a parameter to the\ndecode_predictions\nfunction.\nThe function processes this input data, resulting in a tuple containing (1) the bounding box locations of the text and (2) the corresponding probability of that region containing text:\nrects\n: This value is based on\ngeometry\nand is in a more compact form so we can later apply NMS.\nconfidences\n: The confidence values in this list correspond to each rectangle in\nrects\n.\nBoth of these values are returned by the function.\nNote:\nIdeally, a rotated bounding box would be included in\nrects\n, but it isn’t exactly straightforward to extract a rotated bounding box for today’s proof of concept. Instead, I’ve computed the horizontal bounding rectangle which does take\nangle\ninto account. The\nangle\nis made available on\nLine 41\nif you would like to extract a rotated bounding box of a word to pass into Tesseract.\nFor further details on the code block above, please see\nthis blog post\n.\nFrom there let’s parse our command line arguments:\n# construct the argument parser and parse the arguments\nap = argparse.ArgumentParser()\nap.add_argument(\"-i\", \"--image\", type=str,\n\thelp=\"path to input image\")\nap.add_argument(\"-east\", \"--east\", type=str,\n\thelp=\"path to input EAST text detector\")\nap.add_argument(\"-c\", \"--min-confidence\", type=float, default=0.5,\n\thelp=\"minimum probability required to inspect a region\")\nap.add_argument(\"-w\", \"--width\", type=int, default=320,\n\thelp=\"nearest multiple of 32 for resized width\")\nap.add_argument(\"-e\", \"--height\", type=int, default=320,\n\thelp=\"nearest multiple of 32 for resized height\")\nap.add_argument(\"-p\", \"--padding\", type=float, default=0.0,\n\thelp=\"amount of padding to add to each border of ROI\")\nargs = vars(ap.parse_args())\nOur script\nrequires\ntwo command line arguments:\n--image\n: The path to the input image.\n--east\n: The path to the pre-trained EAST text detector.\nOptionally, the following command line arguments may be provided:\n--min-confidence\n: The minimum probability of a detected text region.\n--width\n: The width our image will be resized to prior to being passed through the EAST text detector. Our detector requires multiples of 32.\n--height\n: Same as the width, but for the height. Again, our detector requires multiple of\n32\nfor resized height.\n--padding\n: The (optional) amount of padding to add to each ROI border. You might try values of\n0.05\nfor 5% or\n0.10\nfor 10% (and so on) if you find that your OCR result is incorrect.\nFrom there, we will load + preprocess our image and initialize key variables:\n# load the input image and grab the image dimensions\nimage = cv2.imread(args[\"image\"])\norig = image.copy()\n(origH, origW) = image.shape[:2]\n\n# set the new width and height and then determine the ratio in change\n# for both the width and height\n(newW, newH) = (args[\"width\"], args[\"height\"])\nrW = origW / float(newW)\nrH = origH / float(newH)\n\n# resize the image and grab the new image dimensions\nimage = cv2.resize(image, (newW, newH))\n(H, W) = image.shape[:2]\nOur\nimage\nis loaded into memory and copied (so we can later draw our output results on it) on\nLines 82 and 83\n.\nWe grab the\noriginal\nwidth and height (\nLine 84\n) and then extract the\nnew\nwidth and height from the\nargs\ndictionary (\nLine 88\n).\nUsing both the original and new dimensions, we calculate ratios used to scale our bounding box coordinates later in the script (\nLines 89 and 90\n).\nOur\nimage\nis then resized,\nignoring aspect ratio\n(\nLine 93\n).\nNext, let’s work with the EAST text detector:\n# define the two output layer names for the EAST detector model that\n# we are interested in -- the first is the output probabilities and the\n# second can be used to derive the bounding box coordinates of text\nlayerNames = [\n\t\"feature_fusion/Conv_7/Sigmoid\",\n\t\"feature_fusion/concat_3\"]\n\n# load the pre-trained EAST text detector\nprint(\"[INFO] loading EAST text detector...\")\nnet = cv2.dnn.readNet(args[\"east\"])\nOur two output layer names are put into list form on\nLines 99-101\n. To learn why these two output names are important, you’ll want to refer to my original\nEAST text detection tutorial\n.\nThen, our pre-trained EAST neural network is loaded into memory (\nLine 105\n).\nI cannot emphasize this enough:\nyou need OpenCV 3.4.2 at a minimum to have the\ncv2.dnn.readNet\nimplementation.\nThe first bit of “magic” occurs next:\n# construct a blob from the image and then perform a forward pass of\n# the model to obtain the two output layer sets\nblob = cv2.dnn.blobFromImage(image, 1.0, (W, H),\n\t(123.68, 116.78, 103.94), swapRB=True, crop=False)\nnet.setInput(blob)\n(scores, geometry) = net.forward(layerNames)\n\n# decode the predictions, then  apply non-maxima suppression to\n# suppress weak, overlapping bounding boxes\n(rects, confidences) = decode_predictions(scores, geometry)\nboxes = non_max_suppression(np.array(rects), probs=confidences)\nTo determine text locations we:\nConstruct a\nblob\non\nLines 109 and 110\n. Read more about the process\nhere\n.\nPass the\nblob\nthrough the neural network, obtaining\nscores\nand\ngeometry\n(\nLines 111 and 112\n).\nDecode the predictions with the previously defined\ndecode_predictions\nfunction (\nLine 116\n).\nApply\nnon-maxima suppression\nvia my\nimutils method\n(\nLine 117\n). NMS effectively takes the most likely text regions, eliminating other overlapping regions.\nNow that we know where the text regions\nare\n, we need to take steps to\nrecognize\nthe text! We begin to loop over the bounding boxes and process the results, preparing the stage for actual\ntext recognition:\n# initialize the list of results\nresults = []\n\n# loop over the bounding boxes\nfor (startX, startY, endX, endY) in boxes:\n\t# scale the bounding box coordinates based on the respective\n\t# ratios\n\tstartX = int(startX * rW)\n\tstartY = int(startY * rH)\n\tendX = int(endX * rW)\n\tendY = int(endY * rH)\n\n\t# in order to obtain a better OCR of the text we can potentially\n\t# apply a bit of padding surrounding the bounding box -- here we\n\t# are computing the deltas in both the x and y directions\n\tdX = int((endX - startX) * args[\"padding\"])\n\tdY = int((endY - startY) * args[\"padding\"])\n\n\t# apply padding to each side of the bounding box, respectively\n\tstartX = max(0, startX - dX)\n\tstartY = max(0, startY - dY)\n\tendX = min(origW, endX + (dX * 2))\n\tendY = min(origH, endY + (dY * 2))\n\n\t# extract the actual padded ROI\n\troi = orig[startY:endY, startX:endX]\nWe initialize the\nresults\nlist to contain our OCR bounding boxes and text on\nLine 120\n.\nThen we begin looping over the\nboxes\n(\nLine 123\n) where we:\nScale the bounding boxes based on the previously computed ratios (\nLines 126-129\n).\nPad the bounding boxes (\nLines 134-141\n).\nAnd finally, extract the padded\nroi\n(\nLine 144\n).\nOur OpenCV OCR pipeline can be completed by using a bit of Tesseract v4 “magic”:\n# in order to apply Tesseract v4 to OCR text we must supply\n\t# (1) a language, (2) an OEM flag of 1, indicating that the we\n\t# wish to use the LSTM neural net model for OCR, and finally\n\t# (3) an OEM value, in this case, 7 which implies that we are\n\t# treating the ROI as a single line of text\n\tconfig = (\"-l eng --oem 1 --psm 7\")\n\ttext = pytesseract.image_to_string(roi, config=config)\n\n\t# add the bounding box coordinates and OCR'd text to the list\n\t# of results\n\tresults.append(((startX, startY, endX, endY), text))\nTaking note of the comment in the code block, we set our Tesseract\nconfig\nparameters on\nLine 151\n(\nEnglish\nlanguage,\nLSTM\nneural network, and\nsingle-lin\ne of text).\nNote:\nYou may need to configure the\n--psm\nvalue using my instructions at the top of this tutorial if you find yourself obtaining incorrect OCR results.\nThe\npytesseract\nlibrary takes care of the rest on\nLine 152\nwhere we call\npytesseract.image_to_string\n, passing our\nroi\nand\nconfig string\n.\n? Boom!\nIn two lines of code, you have used Tesseract v4 to recognize a text ROI in an image. Just remember, there is\na lot happening under the hood\n.\nOur result (the bounding box values and actual\ntext\nstring) are appended to the\nresults\nlist (\nLine 156\n).\nThen we continue this process for other ROIs at the top of the loop.\nNow let’s display/print the results to see if it actually worked:\n# sort the results bounding box coordinates from top to bottom\nresults = sorted(results, key=lambda r:r[0][1])\n\n# loop over the results\nfor ((startX, startY, endX, endY), text) in results:\n\t# display the text OCR'd by Tesseract\n\tprint(\"OCR TEXT\")\n\tprint(\"========\")\n\tprint(\"{}\\n\".format(text))\n\n\t# strip out non-ASCII text so we can draw the text on the image\n\t# using OpenCV, then draw the text and a bounding box surrounding\n\t# the text region of the input image\n\ttext = \"\".join([c if ord(c) < 128 else \"\" for c in text]).strip()\n\toutput = orig.copy()\n\tcv2.rectangle(output, (startX, startY), (endX, endY),\n\t\t(0, 0, 255), 2)\n\tcv2.putText(output, text, (startX, startY - 20),\n\t\tcv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 0, 255), 3)\n\n\t# show the output image\n\tcv2.imshow(\"Text Detection\", output)\n\tcv2.waitKey(0)\nOur results are\nsorted\nfrom top to bottom on\nLine 159\nbased on the\ny\n-coordinate of the bounding box (though you may wish to sort them differently).\nFrom there, looping over the\nresults\n, we:\nPrint the OCR’d\ntext\nto the terminal (\nLines 164-166\n).\nStrip out non-ASCII characters from\ntext\nas OpenCV does not support non-ASCII characters in the\ncv2.putText\nfunction (\nLine 171\n).\nDraw (1) a bounding box surrounding the ROI and (2) the result\ntext\nabove the ROI (\nLines 173-176\n).\nDisplay the output and wait for any key to be pressed (\nLines 179 and 180\n).\nOpenCV text recognition results\nNow that we’ve implemented our OpenCV OCR pipeline, let’s see it in action.\nBe sure to use the\n“Downloads”\nsection of this blog post to download the source code, OpenCV EAST text detector model, and the example images.\nFrom there, open up a command line, navigate to where you downloaded + extracted the zip, and execute the following command:\n$ python text_recognition.py --east frozen_east_text_detection.pb \\\n\t--image images/example_01.jpg\n[INFO] loading EAST text detector...\nOCR TEXT\n========\nOH OK\nFigure 4:\nOur first trial of OpenCV OCR is a success.\nWe’re starting with a simple example.\nNotice how our OpenCV OCR system was able to correctly (1) detect the text in the image and then (2) recognize the text as well.\nThe next example is more representative of text we would see in a real- world image:\n$ python text_recognition.py --east frozen_east_text_detection.pb \\\n\t--image images/example_02.jpg\n[INFO] loading EAST text detector...\nOCR TEXT\n========\n® MIDDLEBOROUGH\nFigure 5:\nA more complicated picture of a sign with white background is OCR’d with OpenCV and Tesseract 4.\nAgain, notice how our OpenCV OCR pipeline was able to correctly localize and recognize the text; however, in our terminal output we see a registered trademark Unicode symbol — Tesseract was likely confused here as the bounding box reported by OpenCV’s EAST text detector bled into the grassy shrubs/plants behind the sign.\nLet’s look at another OpenCV OCR and text recognition example:\n$ python text_recognition.py --east frozen_east_text_detection.pb \\\n\t--image images/example_03.jpg\n[INFO] loading EAST text detector...\nOCR TEXT\n========\nESTATE\n\nOCR TEXT\n========\nAGENTS\n\nOCR TEXT\n========\nSAXONS\nIn this case, there are three separate text regions.\nOpenCV’s text detector is able to localize each of them — we then apply OCR to correctly recognize each text region as well.\nOur next example shows the importance of adding padding in certain circumstances:\n$ python text_recognition.py --east frozen_east_text_detection.pb \\\n\t--image images/example_04.jpg \n[INFO] loading EAST text detector...\nOCR TEXT\n========\nCAPTITO\n\nOCR TEXT\n========\nSHOP\n\nOCR TEXT\n========\n|.\nIn the first attempt of OCR’ing this bake shop storefront, we see that “SHOP” is correctly OCR’d, but:\nThe “U” in “CAPUTO” is incorrectly recognized as “TI”.\nThe apostrophe and “S” is missing from “CAPUTO’S’.\nAnd finally, “BAKE” is incorrectly recognized as a vertical bar/pipe (“|”) with a period (“.”).\nBy adding a bit of padding we can expand the bounding box coordinates of the ROI and correctly recognize the text:\n$ python text_recognition.py --east frozen_east_text_detection.pb \\\n\t--image images/example_04.jpg --padding 0.05\n[INFO] loading EAST text detector...\nOCR TEXT\n========\nCAPUTO'S\n\nOCR TEXT\n========\nSHOP\n\nOCR TEXT\n========\nBAKE\nJust by adding 5% of padding surrounding each corner of the bounding box we’re not only able to correctly OCR the “BAKE” text but we’re also able to recognize the “U” and “’S” in “CAPUTO’S”.\n$ python text_recognition.py --east frozen_east_text_detection.pb \\\n\t--image images/example_05.jpg --padding 0.25\n[INFO] loading EAST text detector...\nOCR TEXT\n========\nDesigner\n\nOCR TEXT\n========\na",
  "metadata": {
    "title": "OpenCV OCR and text recognition with Tesseract - PyImageSearch",
    "description": "Learn how to perform OpenCV OCR (Optical Character Recognition) by applying (1) text detection and (2) text recognition using OpenCV and Tesseract 4.",
    "keywords": null,
    "author": "Adrian Rosebrock",
    "og:locale": "en_US",
    "og:type": "article",
    "og:title": "OpenCV OCR and text recognition with Tesseract - PyImageSearch",
    "og:description": "Learn how to perform OpenCV OCR (Optical Character Recognition) by applying (1) text detection and (2) text recognition using OpenCV and Tesseract 4.",
    "og:url": "https://pyimagesearch.com/2018/09/17/opencv-ocr-and-text-recognition-with-tesseract/",
    "og:site_name": "PyImageSearch",
    "og:image": "https://pyimagesearch.com/wp-content/uploads/2018/09/opencv_ocr_result02.jpg",
    "og:image:width": "600",
    "og:image:height": "486",
    "og:image:type": "image/jpeg",
    "twitter:label1": "Written by",
    "twitter:data1": "Adrian Rosebrock",
    "twitter:label2": "Est. reading time",
    "twitter:data2": "22 minutes",
    "article:published_time": "2018-09-17T14:00:09+00:00",
    "article:modified_time": "2023-03-16T00:19:07+00:00"
  },
  "paywall": {
    "listed_paid": false,
    "detected": false,
    "marker": "",
    "public_only": false,
    "policy": "付费/会员内容只保留页面公开可见部分，不绕过付费墙"
  },
  "crawl": {
    "success": true,
    "status_code": 200,
    "error": ""
  },
  "code_blocks": [
    {
      "file": "attachments/c94e2f5ddd9d/code/body-000.txt",
      "chars": 134,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-001.txt",
      "chars": 33,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-002.txt",
      "chars": 106,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-003.txt",
      "chars": 25,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-004.txt",
      "chars": 24,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-005.txt",
      "chars": 180,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-006.txt",
      "chars": 12,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-007.txt",
      "chars": 69,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-008.txt",
      "chars": 209,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-009.txt",
      "chars": 56,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-010.txt",
      "chars": 45,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-011.txt",
      "chars": 198,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-012.txt",
      "chars": 139,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-013.txt",
      "chars": 39,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-014.txt",
      "chars": 85,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-015.txt",
      "chars": 179,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-016.txt",
      "chars": 830,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-017.txt",
      "chars": 227,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-018.txt",
      "chars": 154,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-019.txt",
      "chars": 1867,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-020.txt",
      "chars": 730,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-021.txt",
      "chars": 459,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-022.txt",
      "chars": 411,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-023.txt",
      "chars": 515,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-024.txt",
      "chars": 844,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-025.txt",
      "chars": 520,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-026.txt",
      "chars": 806,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-027.txt",
      "chars": 160,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-028.txt",
      "chars": 170,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-029.txt",
      "chars": 213,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-030.txt",
      "chars": 209,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-031.txt",
      "chars": 226,
      "language": "text"
    },
    {
      "file": "attachments/c94e2f5ddd9d/code/body-032.txt",
      "chars": 199,
      "language": "text"
    }
  ],
  "images": [
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2020/01/source-code-icon.png?lossy=2&strip=1&webp=1",
      "bytes": 884,
      "reused": false,
      "local_path": "attachments/c94e2f5ddd9d/images/body-0f8ec41d2103feb4399d.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2020/01/source-code-icon.png?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2018/09/opencv_ocr_tesseract.png?lossy=2&strip=1&webp=1",
      "bytes": 14589,
      "reused": true,
      "local_path": "attachments/c94e2f5ddd9d/images/000.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2018/09/opencv_ocr_tesseract.png?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2018/09/opencv_ocr_version_check.png?lossy=2&strip=1&webp=1",
      "bytes": 18902,
      "reused": true,
      "local_path": "attachments/c94e2f5ddd9d/images/002.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2018/09/opencv_ocr_version_check.png?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2018/09/opencv_ocr_pipeline.png?lossy=2&strip=1&webp=1",
      "bytes": 3814,
      "reused": true,
      "local_path": "attachments/c94e2f5ddd9d/images/004.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2018/09/opencv_ocr_pipeline.png?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2018/09/opencv_ocr_result01.jpg?lossy=2&strip=1&webp=1",
      "bytes": 12354,
      "reused": true,
      "local_path": "attachments/c94e2f5ddd9d/images/006.jpg",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2018/09/opencv_ocr_result01.jpg?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2018/09/opencv_ocr_result02.jpg?lossy=2&strip=1&webp=1",
      "bytes": 59941,
      "reused": true,
      "local_path": "attachments/c94e2f5ddd9d/images/008.jpg",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2018/09/opencv_ocr_result02.jpg?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    }
  ],
  "audio": [],
  "videos": [
    {
      "url": "https://www.youtube.com/watch?v=D5tER75G55g",
      "src": "https://www.youtube.com/embed/D5tER75G55g",
      "status": "ok",
      "kind": "single_video",
      "local_path": "attachments/c94e2f5ddd9d/videos/repair-D5tER75G55g.mp4",
      "bytes": 150492276,
      "valid": true,
      "height": 1080,
      "width": 1920,
      "duration": "552.981000",
      "reused": false
    }
  ],
  "links": [
    {
      "href": "https://www.youtube.com/embed/D5tER75G55g",
      "label": "",
      "type": "iframe"
    },
    {
      "href": "https://pyimagesearch.com/2018/08/20/opencv-text-detection-east-text-detector/",
      "label": "perform text detection using OpenCV’s EAST deep learning model",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/wp-content/uploads/2018/09/opencv_ocr_tesseract.png",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/2017/07/10/using-tesseract-ocr-python/",
      "label": "Using Tesseract OCR with Python",
      "type": "a"
    },
    {
      "href": "https://en.wikipedia.org/wiki/Long_short-term_memory",
      "label": "Long Short-Term Memory (LSTM) network",
      "type": "a"
    },
    {
      "href": "https://en.wikipedia.org/wiki/Recurrent_neural_network",
      "label": "Recurrent Neural Network (RNN)",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/opencv-tutorials-resources-guides/",
      "label": "follow one of my OpenCV installation guides",
      "type": "a"
    },
    {
      "href": "https://launchpad.net/~alex-p/+archive/ubuntu/tesseract-ocr",
      "label": "Ubuntu PPA (Personal Package Archive) for Tesseract",
      "type": "a"
    },
    {
      "href": "https://brew.sh/",
      "label": "Homebrew",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/2017/07/03/installing-tesseract-for-ocr/",
      "label": "previous Tesseract install tutorial",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/wp-content/uploads/2018/09/opencv_ocr_version_check.png",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://python-pillow.org/",
      "label": "Pillow",
      "type": "a"
    },
    {
      "href": "https://github.com/thortex/rpi3-tesseract",
      "label": "Thortex’s GitHub",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/wp-content/uploads/2018/09/opencv_ocr_pipeline.png",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://github.com/tesseract-ocr/tesseract/wiki/Data-Files",
      "label": "here",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/2014/11/17/non-maximum-suppression-object-detection-python/",
      "label": "non-maxima suppression",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/2017/11/06/deep-learning-opencvs-blobfromimage-works/",
      "label": "here",
      "type": "a"
    },
    {
      "href": "https://github.com/jrosebr1/imutils/blob/d277bb7118f265d4ef7877817c9a1824e423dc13/imutils/object_detection.py",
      "label": "imutils method",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/wp-content/uploads/2018/09/opencv_ocr_result01.jpg",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/wp-content/uploads/2018/09/opencv_ocr_result02.jpg",
      "label": "",
      "type": "a"
    }
  ],
  "repair_version": 2,
  "repaired_at": "2026-10-14T10:54:12Z",
  "source_url": "https://pyimagesearch.com/2018/09/17/opencv-ocr-and-text-recognition-with-tesseract/",
  "papers": [],
  "actual_video_files": [],
  "body_chars": 29406,
  "expected_body_images": 6,
  "discovery_status": "ok",
  "delivery_status": "ok",
  "missing_reason": "",
  "raw_html": "attachments/c94e2f5ddd9d/pages/source.html",
  "local_html": "attachments/c94e2f5ddd9d/pages/article.html",
  "body_base_path": "attachments/c94e2f5ddd9d/pages/",
  "body_markdown_path": "attachments/c94e2f5ddd9d/pages/article.md"
}