Skip to main content

opencv-text-detection

This is a derivative of pyimagesearch.com OpenCV-text-detection and the OpenCV text detection c++ example

This code began as an attempt to rotate the rectangles found by EAST. The pyimagesearch code doesn't rotate the rectangles due to a limitation in the OpenCV Python bindings -- specifically, there isn't a NMSBoxes call for rotated rectangles (this turns out to be a bigger problem)

EAST is an Efficient and Accurate Scene Text detection pipeline. Adrian's post does a great job explaining EAST. In summary, EAST detects text in an image (or video) and provides geometry and confidence scores for each block of text it detects. Its worth noting that:

  • The geometry of the rectangles is given as offsetX, offsetY, top, right, bottom, left, theta.
  • Top is the distance from the offset point to the top of the rectangle, right is the distance from the offset point to the right edge of the rectangle and so on. The offset point is most likey not the center of the rectangle.
  • The rectangle is rotated around the offset point by theta radians.

While the EAST paper is pretty clear about determining the positioning and size of the rectangle, its not very clear about the rotation point for the rectangle. I used the offset point as it appeared to provide the best visual results.

Modifications

In the PyImageSearch example code, Non Maximal Suppression (NMS) is performed on the results provided by EAST on the unrotated rectangles. The unrotated rectangles returned by NMS are then drawn on the original image.

Initially, I modified the code to rotate the rectangles selected by NMS and then drawing them on the original image. As an example, the images below show the unrotated and rotated rectangles.

Unrotated Rotated
Unrotated Rotated

The Challenge

With my assumption that each rectangle returned by EAST was to be rotated around its offset, I wanted to see how the individual rotations would impact the results of NMS. That is, rather than applying NMS to the EAST rectangles and then drawing them rotated, could I rotate the rectangles and then run them through NMS? This became a challenge as the PyImageSearch imutils and OpenCV Python bindings don't support NMS applied to rectangles rotated about an arbitrary point.

The code in this repo is a result of that challenge. nms.py has three functions for performing NMS:

  • nms_rboxes(rotated_rects, scores)

    rotated_rects is a list of rotated rectangles described by ((cx, cy), (w,h), deg) where (cx, cy) is the center of the rectangle, (w,h) are the width and height and deg is the rotation angle in degrees about the center. The format for rrects was chosen to match the OpenCV c++ implementation of NMSBoxes.

    scores is the corresponding list of confidence scores for the rrects.

    This function converts the list of rotated rectangles into a list of polygons (contours) described by its verticies and passes this list along with other received parameters to nms_polygons.

    Returns a list of indicies of the highest scoring, non-overlapping rotated_rects.

  • nms_polygons(polys, scores)

    polys is a list of polygons, each described by its verticies

    scores is the corresponding list of confidence scores for the rrects.

    Returns a list of indicies of the highest scoring, non-overlapping polys.

  • nms_rects(rects, scores)

    rects is a list of unrotated, upright rectangles each described by (x, y, w, h) where x,y is the upper left corner of the rectangle and w, h are its width and height.

    scores is the corresponding list of confidence scores for the rects.

    Returns a list of indicies of the highest scoring, non-overlapping rects.

Each of the above functions has an optional named parameter nms_function and accept additional parameters that are received as **kwargs.

  • nms_function if specified, must be one of felzenswalb, malisiewicz or fast. If omitted, defaults to malisiewicz. Note that the value for nms_function is not quoted.

The felzenswalb implementation was transmogrified from this PyImageSearch blog post.

indicies = nms_polygons(polygons, scores, nms_function=felzenswalb)

The malisiewicz implementation was transmogrified from this PyImageSearch blog post. Per Adrian's post, this implementation is much faster than felzenswalb but be aware that when running nms_rrects or nms_polygons, some of the vectorization is lost :( and performance suffers a bit.

indicies = nms_polygons(polygons, scores, nms_function=malisiewicz)

The fast implmentation is an approximation of the OpenCV c++ NMSFAST routine. Which, as the inline comments there will tell you, was inspired by Piotr Dollar's NMS implementation in EdgeBox.

indicies = nms_polygons(polygons, scores, nms_function=fast)
  • kwargs are used to pass in custom values. All of these are optional and if not specified, default values are used:

nms_threshold: The value used for making NMS overlap comparisons. Defaults to 0.4 if omitted.

score_threshold: The value used to cull out rectangles/polygons based on their associated score. Defaults to 0.3.

top_k: Used to truncate the scores (after sorting) to include only the top_k scores. If top_k is 0, all scores are included. Default value is 0.

eta is only applicable for fast and is a coefficient in the adaptive threshold formula: nms_thresholdi=eta⋅nms_threshold. The default value is 1.0

As an example of what's possible:

indicies = nms_polygons(polygons, scores, nms_function=fast, nms_threshold=0.45, eta=0.9, score_threshold=0.6, top_k=100)

Results

As you might expect, performing NMS on the rotated rectangles doesn't really change much on images with sparse text like the Lebron images above. However, with busier images there can be a difference -- EAST doesn't perform well with the image below, but it's instrumental for examining the NMS results.

Unrotated Rotated
Unrotated Rotated
Malisiewicz (above) 15 Rectangles 11 Rectangles
Felzenswalb 10 Rectangles 9 Rectangles
Fast 10 Rectangles 9 Rectangles

Run the Code

This code was developed and run on Python 3.7 and OpenCV 4.0.0-pre on OSX. You can find helpful instructions for setting up this environment on yet another PyImageSearch blog post

Clone the repo and run:

python text_detection.py --east frozen_east_text_detection.pb --image images/lebron_james.jpg

What's Next?

I have not implemented text_detection_video.py

There are not any tests.

Thanks

A big thanks to Adrian Rosebrock (@PyImageSearch) at PyImageSearch -- he writes some amazing and inspiring content.

Metadata

Release files for nms 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nms 0.1.0
File Size Uploaded
nms-0.1.0.tar.gz 13.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nms 0.1.0
File Interpreter ABI Platform
nms-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 28.7 kB

Release files / nms-0.1.0.tar.gz

Download URL nms-0.1.0.tar.gz
Size 13.9 kB
Tags Source
SHA-256 checksum
How to use checksums
a618fd39c9b3dd5feafd6e358697ac08a70b2da60806b9ffef22e24240a25d00
BLAKE2b-256 checksum
How to use checksums
412f69656bc005fa81df10a376c08ee37a0fafc065b6f08a183617eebab0b3a3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.11.0 pkginfo/1.4.2 requests/2.19.1 setuptools/40.2.0 requests-toolbelt/0.8.0 tqdm/4.25.0 CPython/3.7.0

Release files / nms-0.1.0-py3-none-any.whl

Download URL nms-0.1.0-py3-none-any.whl
Size 14.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3c2de98a46657703e16dfd3ee5a0679fba900b2265922d58f5edbebe6ebdab7f
BLAKE2b-256 checksum
How to use checksums
2b6b0fab609be987f1d5b84c1cdc3227a78849a46e953a0cfdb68476480c85f6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.11.0 pkginfo/1.4.2 requests/2.19.1 setuptools/40.2.0 requests-toolbelt/0.8.0 tqdm/4.25.0 CPython/3.7.0

Release history Release notifications | RSS feed

0.1.6

2 release files

0.1.5

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page