2016-11-21 113 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中。 –