如何使用OpenCV python自动检测图像的修剪和裁切部分? [英] How to auto detect trim and crop part of image using OpenCV python?

查看:60
本文介绍了如何使用OpenCV python自动检测图像的修剪和裁切部分?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发图像到文本转换程序,该程序要删除周围不必要的图像,背景和文本,以便重点放在要从中提取文本的主要区域!

I am working on image to text convert program where I want to remove surrounding unnecessary images, background and text so that it emphasizes on the main area where I want the text to be extracted from!

请参阅药品包装盒中的警告标签.我如何只提取图像的预期区域!?因为所有其他元素都会引起噪音并影响提取的准确性.

See the warning label from the medicine box. How do I get to extract only the intended area of the image!? Because all the other elements cause noise and effect the accuracy of the extraction.

推荐答案

我的建议是找到轮廓,并且最大子轮廓数.
具有最大子代数的轮廓是其中最大字母数的轮廓.

My suggestion is to find the find the contour with the maximum number of child contours.
The contour with the maximum number of children is the one with maximum letters inside it.

这只是粗略过滤的第一阶段,还有更多阶段:

This is only the first stage for coarse filtering, and there are more stages:

  • 转换为灰度,然后转换为二进制图像.
  • 查找轮廓和层次结构.
    使用 RETR_TREE 在轮廓中创建轮廓树.
  • 查找具有最大子轮廓数的父轮廓.
  • 从图像中裁剪上述轮廓的边界矩形.
  • 找到连接的组件(集群).
  • 删除大,小,高和宽的簇-肯定不是字母.
  • 使用结束"形态学操作来统一文本区域.
  • 查找轮廓,并以最大面积裁剪轮廓的边界矩形.

问题颇具挑战性,我的答案可能与您发布的图片不符.
您可以优化启发式方法以获得更通用的解决方案.

The problem is challenging, and my answer may be over-fitted for the image you posted.
You may refine the heuristics for getting more general solution.

这是代码:

import numpy as np
import cv2

# Read input image
img = cv2.imread('dizziness.jpg')

# Convert to Grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Convert to binary image - use THRESH_OTSU for automatic threshold.
_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

# Find contours and hierarchy, use RETR_TREE for creating a tree of contours within contours
cnts, hiers = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)[-2:]  # [-2:] indexing takes return value before last (due to OpenCV compatibility issues).

# https://docs.opencv.org/master/d9/d8b/tutorial_py_contours_hierarchy.html
# Hierarchy Representation in OpenCV
# So each contour has its own information regarding what hierarchy it is, who is its child, who is its parent etc. 
# OpenCV represents it as an array of four values : [Next, Previous, First_Child, Parent]
parent = hiers[0, :, 3]

# Find parent contour with the maximum number of child contours
# Use np.bincount for counting the number of instances of each parent value.
# https://docs.scipy.org/doc/numpy/reference/generated/numpy.bincount.html#numpy.bincount
hist = np.bincount(np.maximum(parent, 0))
max_n_childs_idx = hist.argmax()

# Get the contour with the maximum child contours
c = cnts[max_n_childs_idx]

# Get bounding rectangle
x, y, w, h = cv2.boundingRect(c)

# Crop the bounding rectangle out of img
img = img[y:y+h, x:x+w, :]
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Convert to binary image (after cropping) and invert polarity
_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

#cv2.imshow('thresh', thresh);cv2.waitKey(0);cv2.destroyAllWindows()

# Find connected components (clusters)
nlabel,labels,stats,centroids = cv2.connectedComponentsWithStats(thresh, connectivity=8)

# Delete large, small, tall and wide clusters - not letters for sure
max_area = 2000
min_area = 10
max_width = 100
max_height = 100
for i in range(1, nlabel):
    if (stats[i, cv2.CC_STAT_AREA] > max_area) or \
       (stats[i, cv2.CC_STAT_AREA] < min_area) or \
       (stats[i, cv2.CC_STAT_WIDTH] > max_width) or \
       (stats[i, cv2.CC_STAT_HEIGHT] > max_height):
        thresh[labels == i] = 0

#cv2.imshow('thresh', thresh);cv2.waitKey(0);cv2.destroyAllWindows()

# Use "closing" morphological operation for uniting text area
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, np.ones((50, 50)))

# Find contours once more
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2]

# Get contour with maximum area
c = max(cnts, key=cv2.contourArea)

# Get bounding rectangle
x, y, w, h = cv2.boundingRect(c)

# Crop the bounding rectangle out of img (leave some margins)
out = img[y-5:y+h+5, x-5:x+w+5]

# Show output
cv2.imshow('out', out);
cv2.waitKey(0);
cv2.destroyAllWindows()


结果:


Result:

这篇关于如何使用OpenCV python自动检测图像的修剪和裁切部分?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆