2013-09-10 18 views
6

Was ich versuche die Anwesenheitsliste zu tun ist, Prozess unter mir zu sagen, wer da ist und wer nicht Attendance SheetOpenCV finden in Kreis und Positionswert Python farbige

Ich bin derzeit matchTemplate mit einem singulären schwarzen Punkt mit die alle aufgefüllten Punkte findet (Bild wird zuerst in Graustufen umgewandelt). Bild unten

Dots Matched

Dann erhalte ich die matchPattern Array manipulieren und etwa in der Mitte eines jeden in der y-Richtung zu bekommen, und ich kann sehen, wo es Lücken zu fehlen Studenten entsprechen.

Das Problem, das ich habe, ist sicher, dass dieser Sorta funktioniert für perfekte Eingabe, aber mein Ziel ist es, in der Lage zu sein, ein Bild von dem physischen Stück Papier zu machen und dies zu verarbeiten? Hinweis: Das Anwesenheitsblatt wird von mir erstellt, damit es geändert/geändert werden kann, wie auch immer es notwendig ist.

Ich habe ein Beispielbild beigefügt, um unten zu entsprechen. test match Die Verwendung meiner aktuellen Methode ist nur eine Katastrophe (siehe unten). Jetzt bin ich mir nicht sicher, wohin ich von hier aus gehen soll. Ich habe versucht, den Schwellenwert zu ändern, aber nach .65 konnte ich keine Bilder finden. fail

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

values = [] 
img_rgb = cv2.imread('/home/user/Downloads/input.png') 
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY) 
template = cv2.imread('/home/user/Downloads/input_2.png',0) 
w, h = template.shape[::-1] 

res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED) 
threshold = 0.6 
loc = np.where(res >= threshold) 
for pt in zip(*loc[::-1]): 
    cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2) 
    values.append(pt[1]+h/2) 

cv2.imwrite('output.png',img_rgb) 
values.sort() 
pivot = values[0] 
count = 1 
total = values[0] 
cleaned = [] 

for x in range(1,len(values)): 
    if(values[x] < pivot+20): 
    pivot = values[x] 
    count = count + 1 
    total = total + values[x] 
    else: 
    print values[x] 
    cleaned.append(int(total/count)) 
    pivot = values[x] 
    count = 1 
    total = values[x] 

    if x == len(values)-1: 
    cleaned.append(int(total/count)) 
print values 
print cleaned 

Hier ist ein weiteres Testbild: enter image description here

Antwort

3

Normalerweise, wenn Papierformulare Analyse spezielle Markierungen auf Ränder und Ecken Form verwendet werden Maßstab und Orientierung von sinnvollen Teile zu identifizieren. Zum Beispiel können Sie mehrere kleine schwarze Quadrate an den Rändern des Formulars drucken, sie mit demselben cv2.matchTemplate finden und so den Bereich von Interesse definieren.

Höchstwahrscheinlich werden Ihre Formulare nicht perfekt erfasst (z. B. können sie skaliert, gedreht oder perspektivisch dargestellt werden). Daher müssen Sie auch die Eingabe normalisieren. Sie können hierfür perspective or affine transformations verwenden.

Sie können auch Bild verbessern wollen, indem Sie Histogrammausgleich, denoising und andere Techniken.

An diesem Punkt sollte das Bild vollständig normalisiert sein, was viel näher an einer "perfekten Eingabe" liegt. Sie können Ihren Algorithmus an dieser Eingabe ausprobieren, aber es gibt auch einen einfacheren Weg (AFAIK, so etwas wird in realen Anwendungen für die automatische Formularanalyse verwendet).

Ihr Formular hat ein festes Layout und Sie kennen seine Ecken bereits. Warum also nicht die Position jedes interessanten Stücks des Formulars berechnen? Z.B. Im Bild unten habe ich 4 schwarze Landmarken an den Ecken des Formulars platziert. In einem normalisierten Bild Position des gestrichelten Bereichs wird immer das gleiche relativ zu diesen Orientierungspunkten sein.

enter image description here

herauszufinden, ob Student auf dem Vortrag war oder nicht, ist so einfach wie das Aufspalten gestrichelte Fläche in festen quadratische Bereiche (einen pro Student), Pixelwerte in diesem Bereich Summieren und diesen Wert mit einem vordefinierten Schwellenwert zu vergleichen .Regionen mit niedrigeren Werten sind tendenziell eher schwarz als weiß (Schüler besuchten die Vorlesung), während Regionen mit hohen Werten höchstwahrscheinlich weiß sind (Student war abwesend).

Also, um es zusammenzufassen:

  1. Verwenden Sehenswürdigkeiten Ecken des Papiers zu definieren.
  2. Normalisieren Sie das Bild in Bezug auf diese Landmarken.
  3. Bild bei Bedarf verbessern.
  4. Positionen von Bereichen von Interesse berechnen.
  5. Bestimmen Sie, ob Region eher schwarzweiß ist.
2

Hier ist ein Beispiel dafür, wie die Punkte mit einem ziemlich vereinfachenden Ansatz zu identifizieren:

from skimage import io, color, filter, morphology, feature, img_as_float 
from skimage.morphology import disk 

image = io.imread('dots.jpg') 

# Remove blue channel 
bw = image.copy() 
bw[..., 2] = 0 

bw = 1 - img_as_float(color.rgb2gray(image)) 

big_mask = 150 
small_mask = 10 
min_dist = 50 

bw = filter.rank.threshold_percentile(bw, disk(big_mask), p0=0.95) 
bw = morphology.erosion(bw, disk(small_mask)) 

peaks = feature.corner_peaks(bw, min_distance=min_dist, indices=True) 

import matplotlib.pyplot as plt 
f, (ax0, ax1) = plt.subplots(1, 2) 

ax0.imshow(image, cmap=plt.cm.gray) 
ax1.imshow(bw, cmap=plt.cm.gray) 
ax0.scatter(peaks[:, 1], peaks[:, 0], c='red', s=30) 

plt.show() 

Detected dots