2016-11-21 120 views

回答

2

作为一个起点,我会尝试以下方法:

  1. 使用OTSU阈值。
  2. 比做一些形态学操作来摆脱噪音并隔离每个数字。
  3. 运行连接组件labling。
  4. 将每个连接的组件送到您的分类器,以便在分类得分低丢弃时识别数字。
  5. 最终确认你期望所有的数字或多或少处于在线状态,并且或多或少地与彼此之间保持一定的距离。

以下是前4个阶段。现在您需要添加识别软件来识别数字。

import cv2 
import numpy as np 
from matplotlib import pyplot as plt 

# Params 
EPSSILON = 0.4 
MIN_AREA = 10 
BIG_AREA = 75 

# Read img 
img = cv2.imread('i.jpg',0) 

# Otzu threshold 
a,thI = cv2.threshold(img,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU) 

# Morpholgical 
se = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(1,1)) 
thIMor = cv2.morphologyEx(thI,cv2.MORPH_CLOSE,se) 

# Connected compoent labling 
stats = cv2.connectedComponentsWithStats(thIMor,connectivity=8) 

num_labels = stats[0] 
labels = stats[1] 
labelStats = stats[2] 

# We expect the conneccted compoennt of the numbers to be more or less with a constats ratio 
# So we find the medina ratio of all the comeonets because the majorty of connected compoent are numbers 
ratios = [] 
for label in range(num_labels): 

    connectedCompoentWidth = labelStats[label,cv2.CC_STAT_WIDTH] 
    connectedCompoentHeight = labelStats[label, cv2.CC_STAT_HEIGHT] 

    ratios.append(float(connectedCompoentWidth)/float(connectedCompoentHeight)) 

# Find median ratio 
medianRatio = np.median(np.asarray(ratios)) 

# Go over all the connected component again and filter out compoennt that are far from the ratio 
filterdI = np.zeros_like(thIMor) 
filterdI[labels!=0] = 255 
for label in range(num_labels): 

    # Ignore biggest label 
    if(label==1): 
     filterdI[labels == label] = 0 
     continue 

    connectedCompoentWidth = labelStats[label,cv2.CC_STAT_WIDTH] 
    connectedCompoentHeight = labelStats[label, cv2.CC_STAT_HEIGHT] 

    ratio = float(connectedCompoentWidth)/float(connectedCompoentHeight) 
    if ratio > medianRatio + EPSSILON or ratio < medianRatio - EPSSILON: 
     filterdI[labels==label] = 0 

    # Filter small or large compoennt 
    if labelStats[label,cv2.CC_STAT_AREA] < MIN_AREA or labelStats[label,cv2.CC_STAT_AREA] > BIG_AREA: 
     filterdI[labels == label] = 0 

plt.imshow(filterdI) 


# Now go over each of the left compoenet and run the number recognotion 
stats = cv2.connectedComponentsWithStats(filterdI,connectivity=8) 
num_labels = stats[0] 
labels = stats[1] 
labelStats = stats[2] 

for label in range(num_labels): 

    # Crop the bounding box around the component 
    left = labelStats[label,cv2.CC_STAT_LEFT] 
    top = labelStats[label, cv2.CC_STAT_TOP] 
    width = labelStats[label, cv2.CC_STAT_WIDTH] 
    height = labelStats[label, cv2.CC_STAT_HEIGHT] 
    candidateDigit = labels[top:top+height,left:left+width] 


    # plt.figure(label) 
    # plt.imshow(candidateDigit) 

OTSU thrshold image

+1

2和3的任何想法?请多一点信息? – donpresente

+0

for 2请看http://docs.opencv.org/2.4/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.html –

+0

查看http://docs.opencv.org/2.4/doc/tutorials/imgproc /shapedescriptors/find_contours/find_contours.html –

0

我连接到Amitay答案。

为2: 我会用细化的形态操作(看thinning algorithm in opencv

对于3: 而在OpenCV的3.0已经有一个叫做cv::connectedComponents)功能

希望它可以帮助

+1

谢谢。你在Python中有相同的文档吗? – donpresente

+0

对于OpenCV,通常功能与C++的功能完全相同,因此cv2.connectedComponents应该完成这项工作。 –

+1

至于细化算法我没有对Python代码的引用,但是如果你阅读它很容易在python中进行转置,我相信你将没有困难,它只是再次使用对应的opencv函数在python中。 –