OpenCV Contours war für mich nicht ganz verständlich, deshalb bin ich bei dem alten Algorithmus geblieben und habe mir die Tipps von "@Sirius3" zu Herzen genommen.
Hierbei sei gesagt, dass es das erste Mal Python programmieren war, weshalb ich auch keine Ahnung von der Grammatik hatte.
Code: Alles auswählen
import cv2
import numpy
from PIL import Image
# erstellt pixel matrix in Größe des Bildes: 0 = unbenutzt, 1 = benutzt
def createPixelList(size_x_1, size_y_1):
pixel_list = numpy.zeros((size_x_1, size_y_1))
return pixel_list
# erstellt pixel matrix in Größe des Bildes: 0 = unbenutzt, 1 = benutzt
def createZonePixelList(size_x_1, size_y_1):
zone_pixel_list = numpy.zeros((size_x_1, size_y_1))
return zone_pixel_list
# überprüft Nachbarn des Pixels
def checkNeighbour(x, y, pixel_matrix, pixel_zone_matrix, pixel_colour, colour_of_zone, size_x, size_y, index_of_zone, colour_toleranz):
# erstellt Array der Zone [x,y]
zone = []
# erstellt Warteschlangenarray [x,y]
queue_to_check = [[x, y]]
# hakt Pixel ab, dass er einer Zone hinzugefügt wurde
pixel_matrix[x, y] = True
# trägt dem Pixel seine Zone als Integer ein
pixel_zone_matrix[x, y] = index_of_zone
# solange ein Pixel in der Warteschlange ist
while len(queue_to_check) >= 1:
# übernimmt ersten Pixel aus der Warteschlange, entfernt diesen dort und fügt Zone hinzu
x_to_check = queue_to_check[0][0]
y_to_check = queue_to_check[0][1]
queue_to_check.pop(0)
zone.append([x_to_check, y_to_check])
# prüft von-Neumann-Nachbarn oben
if y_to_check != 0 and not pixel_matrix[x_to_check, y_to_check - 1]:
# nehme Farbe des zu prüfenden Pixels und schaue, ob diese im Toleranz Bereich zur Zone liegt
colour = pixel_colour[x_to_check, y_to_check - 1]
if colour_of_zone[0] + colour_toleranz >= colour[0] >= colour_of_zone[0] - colour_toleranz and colour_of_zone[1] + colour_toleranz >= colour[1] >= \
colour_of_zone[1] - colour_toleranz and colour_of_zone[2] + colour_toleranz >= colour[2] >= \
colour_of_zone[2] - colour_toleranz:
# füge Pixel zur Warteschlange hinzu, trage ihn als Zone zugewiesen ein und trage Zonen index ein
queue_to_check.append([x_to_check, y_to_check - 1])
pixel_matrix[x_to_check, y_to_check - 1] = True
pixel_zone_matrix[x_to_check, y_to_check - 1] = index_of_zone
# prüft von-Neumann-Nachbarn rechts
if x_to_check + 1 < size_x and not pixel_matrix[x_to_check + 1, y_to_check]:
# nehme Farbe des zu prüfenden Pixels und schaue, ob diese im Toleranz Bereich zur Zone liegt
colour = pixel_colour[x_to_check + 1, y_to_check]
if colour_of_zone[0] + colour_toleranz >= colour[0] >= colour_of_zone[0] - colour_toleranz and colour_of_zone[1] + colour_toleranz >= colour[1] >= \
colour_of_zone[1] - colour_toleranz and colour_of_zone[2] + colour_toleranz >= colour[2] >= \
colour_of_zone[2] - colour_toleranz:
# füge Pixel zur Warteschlange hinzu, trage ihn als Zone zugewiesen ein und trage Zonen index ein
queue_to_check.append([x_to_check + 1, y_to_check])
pixel_matrix[x_to_check + 1, y_to_check] = True
pixel_zone_matrix[x_to_check + 1, y_to_check] = index_of_zone
# prüft von-Neumann-Nachbarn unten
if y_to_check + 1 < size_y and not pixel_matrix[x_to_check, y_to_check + 1]:
# nehme Farbe des zu prüfenden Pixels und schaue, ob diese im Toleranz Bereich zur Zone liegt
colour = pixel_colour[x_to_check, y_to_check + 1]
if colour_of_zone[0] + colour_toleranz >= colour[0] >= colour_of_zone[0] - colour_toleranz and colour_of_zone[1] + colour_toleranz >= colour[1] >= \
colour_of_zone[1] - colour_toleranz and colour_of_zone[2] + colour_toleranz >= colour[2] >= \
colour_of_zone[2] - colour_toleranz:
# füge Pixel zur Warteschlange hinzu, trage ihn als Zone zugewiesen ein und trage Zonen index ein
queue_to_check.append([x_to_check, y_to_check + 1])
pixel_matrix[x_to_check, y_to_check + 1] = True
pixel_zone_matrix[x_to_check, y_to_check + 1] = index_of_zone
# prüft von-Neumann-Nachbarn links
if x != 0 and not pixel_matrix[x_to_check - 1, y_to_check]:
# nehme Farbe des zu prüfenden Pixels und schaue, ob diese im Toleranz Bereich zur Zone liegt
colour = pixel_colour[x_to_check - 1, y_to_check]
if colour_of_zone[0] + colour_toleranz >= colour[0] >= colour_of_zone[0] - colour_toleranz and colour_of_zone[1] + colour_toleranz >= colour[1] >= \
colour_of_zone[1] - colour_toleranz and colour_of_zone[2] + colour_toleranz >= colour[2] >= \
colour_of_zone[2] - colour_toleranz:
# füge Pixel zur Warteschlange hinzu, trage ihn als Zone zugewiesen ein und trage Zonen index ein
queue_to_check.append([x_to_check - 1, y_to_check])
pixel_matrix[x_to_check - 1, y_to_check] = True
pixel_zone_matrix[x_to_check - 1, y_to_check] = index_of_zone
return zone, pixel_matrix, pixel_zone_matrix
# merged die kleinen Zonen in größere
def mergeSmallZones(zone_list, zonen_toleranz, pixel_zone_matrix, size_x):
# geht komplette Zonen Liste durch
for zone in range(0, int(len(zone_list))):
# wenn die Zone < zonen_toleranz
if int(len(zone_list[zone])) < zonen_toleranz:
# nimm ersten Pixel aus der Zone
pixel = zone_list[zone][0]
pxl_x = pixel[0]
pxl_y = pixel[1]
# nimm den Zonen Index dieses Pixels
index_of_pixel = int(pixel_zone_matrix[pxl_x, pxl_y])
# speichert den neuen Zonen Index des Pixels ab
new_index = 0
# solange Nachbar Pixel zur selben Zone gehört, wird dieser Wert erhöht
check_index = 1
checked = False
while not checked:
# prüft von-Neumann-Nachbarn oben, ob der Pixel zu einer anderen Zone gehört
if pxl_x - check_index >= 0 and pixel_zone_matrix[pxl_x - check_index, pxl_y] != index_of_pixel:
# möglicher neuer Index wird auf länge der Zone geprüft
ind = int(pixel_zone_matrix[pxl_x - check_index, pxl_y])
if len(zone_list[ind]) > 50:
new_index = pixel_zone_matrix[pxl_x - check_index, pxl_y]
break
# prüft von-Neumann-Nachbarn unten, ob der Pixel zu einer anderen Zone gehört
if pxl_x + check_index < size_x and pixel_zone_matrix[pxl_x + check_index, pxl_y] != index_of_pixel:
# möglicher neuer Index wird auf länge der Zone geprüft
ind = int(pixel_zone_matrix[pxl_x + check_index, pxl_y])
if len(zone_list[ind]) > 50:
new_index = pixel_zone_matrix[pxl_x + check_index, pxl_y]
break
# erhöhe den Abstand zu nächsten Pixel
check_index = check_index + 1
# füge alle Pixel der kleinen Zone der neuen großen Zone hinzu und trage Zonen Index neu ein
for p in range(0, len(zone_list[index_of_pixel])):
zone_list[int(new_index)].append(zone_list[index_of_pixel][p])
old_x = zone_list[index_of_pixel][p][0]
old_y = zone_list[index_of_pixel][p][1]
pixel_zone_matrix[old_x, old_y] = int(new_index)
# lösche alle kleinen Zonen aus gesamter Zonen Liste
delete = []
# füge kleine Zonen der Löschliste hinzu = immer vorne einfügen, sonst ändert sich der Index all der anderen Zonen beim Entfernen
for zone in range(0, int(len(zone_list))):
if int(len(zone_list[zone])) < zonen_toleranz:
delete.insert(0, zone)
# entferne kleine Zonen aus der gesamten Zonen Liste
for zone in range(0, len(delete)):
zone_list.pop(delete[zone])
return zone_list, pixel_zone_matrix
# print the edge image
def createEdgeImage(size_x, size_y, image_edge, edge_pixel_matrix, pixel_zone_matrix):
for x in range(0, size_x):
for y in range(0, size_y):
if not edge_pixel_matrix[x, y]:
zone_index = pixel_zone_matrix[x, y]
image_edge = checkNewEdge(size_x, size_y, x, y, edge_pixel_matrix, zone_index, pixel_zone_matrix, image_edge)
image_edge.save("Edge.jpg")
return image_edge
# Method to print all the edges
def checkNewEdge(size_x, size_y, x_to_check, y_to_check, edge_pixel_matrix, zone_index, pixel_zone_matrix, image_edge):
# erstellt warteschlange
queue_to_check = [[x_to_check, y_to_check]]
# trägt pixel als bereits geprüften Pixel ein
edge_pixel_matrix[x_to_check, y_to_check] = True
# solange ein Pixel in der Warteschlange ist
while len(queue_to_check) >= 1:
# nimm Pixel zu prüfen
x_to_check = queue_to_check[0][0]
y_to_check = queue_to_check[0][1]
# lösche Pixel aus Warteschlange
queue_to_check.pop(0)
# prüft von-Neumann-Nachbarn oben
if y_to_check != 0 and not edge_pixel_matrix[x_to_check, y_to_check - 1]:
this_index = pixel_zone_matrix[x_to_check, y_to_check - 1]
if zone_index == this_index:
queue_to_check.append([x_to_check, y_to_check - 1])
edge_pixel_matrix[x_to_check, y_to_check - 1] = True
else:
image_edge.putpixel((x_to_check, y_to_check), (0, 0, 0))
# prüft von-Neumann-Nachbarn rechts
if x_to_check + 1 < size_x and not edge_pixel_matrix[x_to_check + 1, y_to_check]:
this_index = pixel_zone_matrix[x_to_check + 1, y_to_check]
if zone_index == this_index:
queue_to_check.append([x_to_check + 1, y_to_check])
edge_pixel_matrix[x_to_check + 1, y_to_check] = True
else:
image_edge.putpixel((x_to_check, y_to_check), (0, 0, 0))
# prüft von-Neumann-Nachbarn unten
if y_to_check + 1 < size_y and not edge_pixel_matrix[x_to_check, y_to_check + 1]:
this_index = pixel_zone_matrix[x_to_check, y_to_check + 1]
if zone_index == this_index:
queue_to_check.append([x_to_check, y_to_check + 1])
edge_pixel_matrix[x_to_check, y_to_check + 1] = True
else:
image_edge.putpixel((x_to_check, y_to_check), (0, 0, 0))
# prüft von-Neumann-Nachbarn links
if x_to_check != 0 and not edge_pixel_matrix[x_to_check - 1, y_to_check]:
this_index = pixel_zone_matrix[x_to_check - 1, y_to_check]
if zone_index == this_index:
queue_to_check.append([x_to_check - 1, y_to_check])
edge_pixel_matrix[x_to_check - 1, y_to_check] = True
else:
image_edge.putpixel((x_to_check, y_to_check), (0, 0, 0))
return image_edge
# gibt die zone als Bild aus
def printImage(zone_list, zonen_toleranz, font_size):
# liest das Kanten Bild ein, um dort die Zahlen einzuzeichnen
im = cv2.imread("Edge.jpg")
# geht alle Zonen durch
for p in range(0, len(zone_list)):
# wenn die Zone groß genug ist
if len(zone_list[p]) >= zonen_toleranz:
# teile die Zone durch 2 und zeichne auf Pixel die Zahl
mid = int(len(zone_list[p]) / 2)
mid_item = zone_list[p].__getitem__(mid)
x_mid = mid_item[0]
y_mid = mid_item[1]
font = cv2.FONT_HERSHEY_SIMPLEX
position = (x_mid, y_mid)
fontScale = font_size
fontColor = (0, 0, 0)
cv2.putText(im, '1',
position,
font,
fontScale,
fontColor)
# zeichnet und speichert das neue Bild
cv2.imshow('image', im)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite("Fertig.jpg", im)
# Main Methode
def main():
# Spielraum der farbe
colour_toleranz = 10
# kleinste größe für Zellen
zonen_toleranz = 100
# größe der Zahlen
font_size = 0.2
# liest kmeans Bild ein und lädt Matrix mit Pixel Farben
image = Image.open('Fisch.jpg')
pixel_colour = image.load()
# erstellt eine Liste für alle Zonen, die erkannt werden
zone_list = []
# breite und höhe des Bildes
size_x, size_y = image.size
# erstellt boolean Matrix in größe des Bildes um erkannte Pixel abzuhaken
pixel_matrix = createPixelList(size_x, size_y)
# erstellt integer Matrix in größe des Bildes, um Zone des Pixels einzutragen
pixel_zone_matrix = createZonePixelList(size_x, size_y)
# Zonen Index, um den verschiedenen Pixeln eine Zone zuzuweisen
index_of_zone = 0
# gehe Pixel für Pixel des Bildes durch
for x in range(0, size_x):
for y in range(0, size_y):
# wenn der Pixel zu keiner Zone gehört, suche alle Pixel, die aneinander liegen und dieselbe Farbe haben
if not pixel_matrix[x, y]:
colour_of_zone = pixel_colour[x, y]
zone, pixel_matrix, pixel_zone_matrix = checkNeighbour(x, y, pixel_matrix, pixel_zone_matrix,
pixel_colour, colour_of_zone, size_x, size_y,
index_of_zone, colour_toleranz)
zone_list.append(zone)
# erhöht Zonen Index nach erkannter Zone
index_of_zone = index_of_zone + 1
# merge alle kleinen Zonen in große Zonen
zone_list, pixel_zone_matrix = mergeSmallZones(zone_list, zonen_toleranz, pixel_zone_matrix, size_x)
# erstellt das Kanten Bild und die dazugehörige boolean Matrix
image_edge = Image.new("RGB", (size_x, size_y), (255, 255, 255))
edge_pixel_matrix = createZonePixelList(size_x, size_y)
# filtert alle Kanten und zeichnet sie in das Bild
image_edge = createEdgeImage(size_x, size_y, image_edge, edge_pixel_matrix, pixel_zone_matrix)
# zeichne das Zahlen Bild
printImage(zone_list, zonen_toleranz, font_size)
if __name__ == "__main__":
main()
Ich hoffe diesmal íst die Grammatik besser.
Der Algorithmus macht nun alles was ich brauchte.
Falls also jemand die selben Probleme hat wie ich, habt ihr hier nun den Code.
Vielen Dank an Alle.