[PYTHON] Ich habe versucht, das Bild des Bogenschießen-Bewertungsbuchs (eine Broschüre, in der die Ergebnisse von Treffern aufgezeichnet werden) zu analysieren. (Google Colaboratory)

Was ist ein Bogenschießen-Bewertungsbuch?

Dies ist eine Broschüre, in der aufgezeichnet wird, ob der Schusspfeil getroffen oder verfehlt wurde.

Je nach Gruppe gibt es verschiedene Aufnahmemethoden, aber diesmal habe ich mich der Herausforderung gestellt, diejenigen zu analysieren, die mit einem Kreis in zinnoberroter Tinte markiert sind.

saitenbo_sample1.png

Es ist ein schlechter Code, aber ich hoffe, er hilft jemandem.

Struktur dieses Programms

Google Collaboratery verwenden

Ich habe das Programm unter der Annahme erstellt, dass ** Google Collaboratery ** verwendet wird.

https://colab.research.google.com/notebooks/welcome.ipynb?hl=ja

Google Collab ist eine Jupyter-Notebook-Umgebung, die vollständig in der Cloud ausgeführt wird. Sie haben keinen Computer, weil Sie ihn ohne Einstellungen kostenlos nutzen können! Zu diesem Zeitpunkt habe ich Python noch nicht auf meinem Computer installiert! Auch in diesem Fall ist es einfach zu bedienen.

Obwohl die Installation der Bibliothek auf Ihrem eigenen Computer einige Zeit in Anspruch nimmt, ist es ein überraschend großer Vorteil, dass Sie sie mit Hirntod ausführen können, da die meisten Bibliotheken bereits in Google Collab installiert sind.

Dieses Mal werde ich Bilder lesen und schreiben, also habe ich beschlossen, sie mit ** google Drive ** zu verknüpfen.

Elektronischer Datenkonvertierungsplan

Das Design dieses Codes ist wie folgt.

** 1. Verknüpfen Sie mit Google Drive, um Ordner zu erstellen 2. Bild abrufen, Bildgröße ändern 3. Erkennen Sie den Rahmen des Bewertungsbuchs 4. Erkennen Sie den roten Kreis im Bewertungsbuch 5. Ordnen Sie die Positionsinformationen des Kreises an 6. Schreiben Sie in Excel **

Erkennung des äußeren Rahmens der Broschüre

Unter bestimmten Bedingungen wurde eine gerade Linie erkannt, und die vertikalen und horizontalen Linien an den Bildrändern wurden als Rückgabewerte angegeben.

http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_houghlines/py_houghlines.html

detect_line.py



  def resize_im(self, im): #Feste Bildgröße
  # --------------------------------------------
    size = self.x_pixel
    h, w, c = im.shape
    width,height = size, round(size * ( h / w ))
    im_resize = cv2.resize(im,(width, height))
    return im_resize


  def detect_line(self): #Frames erkennen
  # -----------------------------------------
    im = cv2.imread(path_Now_Projects + self.FileName)
    im_resize = self.resize_im(im)
    # parameter
    G = 1 + 2 * self.nomalization(10)
    T1 = 1 + 2 * self.nomalization(7)
    T2 = 1 + 2 * self.nomalization(2)

    #Bild verarbeiten (Rauschunterdrückung, Unschärfe, Binarisierung)
    im_denoise = cv2.fastNlMeansDenoising(im_resize)
    im_gray = cv2.cvtColor(im_denoise, cv2.COLOR_BGR2GRAY)
    im_gau = cv2.GaussianBlur(im_gray,(G,G),0)
    im_th = cv2.adaptiveThreshold(im_gau, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY,T1,T2)
    if detail2 == True:
      cv2.imwrite(self.path_project + self.ImName + "_th.jpg ", im_th)
    #Extrahieren Sie eine gerade Linie.
    imgEdge = cv2.Canny(im_th,50,150,apertureSize = 3) #Kantenerkennung nach Canny-Methode
    minLineLength = self.nomalization(200) #Schwellenwert für die Länge der zu erkennenden geraden Linie (abhängig von der Anzahl der Pixel)
    maxLineGap = self.nomalization(20) #Der längste Abstand zwischen geraden Linien, der als durchgehend angesehen werden kann (abhängig von der Anzahl der Pixel)
    th = self.nomalization(50)
    lines = cv2.HoughLinesP(imgEdge,2,np.pi/180,th,minLineLength=minLineLength,maxLineGap=maxLineGap) #Erkennung von Geraden durch Huff-Näherung
    #Wählen Sie die geraden Linien des Rahmens aus, während Sie die geraden Linien in Blau zeichnen.
    im_line = im_resize
    frame_left,frame_under, frame_over, frame_right = [10000]*4,[1]*4, [10000]*4, [1]*4 #Anfangswerteinstellung
    #Zeichnen Sie alle geraden Linien
    for i in range(len(lines)):
      for x1,y1,x2,y2 in lines[i]:
        cv2.line(im_line,(x1,y1),(x2,y2),(255,0,0),2)

        #Sortieren der geraden Linien des Rahmens
        if frame_left[0] > x1 and abs(y1-y2) >3*abs(x1-x2) : #Vertikale Linie mit der kleinsten x-Koordinate
          frame_left = [x1,y1,x2,y2]
        if frame_under[1] < y1 and 3*abs(y1-y2) < abs(x1-x2) : #Horizontale Linie mit der größten y-Koordinate
          frame_under = [x1,y1,x2,y2]
        if frame_over[1] > y1 and 3*abs(y1-y2) < abs(x1-x2) : #Horizontale Linie mit der kleinsten y-Koordinate
          frame_over = [x1,y1,x2,y2]
        if frame_right[0]  < x1 and abs(y1-y2) >3*abs(x1-x2) : #Vertikale Linie mit der größten x-Koordinate
          frame_right = [x1,y1,x2,y2]
    #Zeichnen Sie eine gerade Linie, die den Rahmen in Grün anzeigt.
    cv2.line(im_line,(frame_left[0], frame_left[1]),(frame_left[2], frame_left[3]),(0,255,0),2)
    cv2.line(im_line,(frame_under[0], frame_under[1]),(frame_under[2], frame_under[3]),(0,255,0),2)
    cv2.line(im_line,(frame_over[0], frame_over[1]),(frame_over[2], frame_over[3]),(0,255,0),2)
    cv2.line(im_line,(frame_right[0], frame_right[1]),(frame_right[2], frame_right[3]),(0,255,0),2)

    if detail2 == True: #Speichern Sie das Image zum Debuggen.
      cv2.imwrite(self.path_project + self.ImName + "_line.jpg ", im_line)
    return frame_left, frame_under, frame_over, frame_right



Finden Sie den Schnittpunkt jeder der vier geraden Linien

get_4point.py


  def cross_point(self, p1, p2): #Ableitung des Schnittpunkts zweier gerader Linien, die durch zwei Punkte verlaufen
  # -----------------------------------------------------------
    return solve( [ solve(p1,[1,1]), solve(p2,[1,1]) ], [1,1] )



  def get_4point(self, f_under, f_left,f_over,f_right):#Erhalten Sie 4 Schnittpunkte von 4 geraden Linien, die durch 2 Punkte verlaufen
  # ------------------------------------------------------------------------------------
    f_under = np.array([f_under[0:2], f_under[2:4]])
    f_left = np.array([f_left[0:2], f_left[2:4]])
    f_over = np.array([f_over[0:2], f_over[2:4]])
    f_right = np.array([f_right[0:2], f_right[2:4]])
    UL = self.cross_point(f_under, f_left)
    OL = self.cross_point(f_over , f_left)
    UR = self.cross_point(f_under, f_right)
    OR = self.cross_point(f_over, f_right)
    return  [OL, OR, UL, UR]

Trimmen eines Vierecks an 4 beliebigen Punkten

transform_by4.py


  def transform_by4(self, points):#Schneiden Sie von 4 beliebigen Punkten zu einem Rechteck
  # --------------------------------------------------------------
    im = cv2.imread(path_Now_Projects + self.FileName)
    im_resize = self.resize_im(im)
    points = sorted(points, key=lambda x:x[1])  #Sortieren Sie in aufsteigender Reihenfolge von y.
    top = sorted(points[:2], key=lambda x:x[0])  #Die ersten beiden sind auf dem Platz. Sie können auch links und rechts sehen, indem Sie nach x sortieren.
    bottom = sorted(points[2:], key=lambda x:x[0], reverse=True)  #Die beiden letzteren befinden sich unterhalb des Quadrats. Auch sortiert nach x.
    points = np.array(top + bottom, dtype='float32')  #Verbinden Sie die beiden getrennten Teile wieder.
    width = max(np.sqrt(((points[0][0]-points[2][0])**2)*2), np.sqrt(((points[1][0]-points[3][0])**2)*2))
    height = max(np.sqrt(((points[0][1]-points[2][1])**2)*2), np.sqrt(((points[1][1]-points[3][1])**2)*2))
    dst = np.array([
      np.array([0, 0]),
      np.array([width-1, 0]),
      np.array([width-1, height-1]),
      np.array([0, height-1]),
      ], np.float32)
    trans = cv2.getPerspectiveTransform(points, dst)  #Wenn Sie die Entsprechung zwischen den Koordinaten vor der Konvertierung und den Koordinaten nach der Konvertierung übergeben, wird eine perspektivische Konvertierungsmatrix erstellt.
    im_trimming = cv2.warpPerspective(im_resize, trans, (int(width), int(height)))  #Zuschneiden mit einer perspektivischen Transformationsmatrix.

    if detail2 == True:
      cv2.imwrite(self.path_project +  self.ImName +'_trimming.jpg', im_trimming)
    return im_trimming

Extraktion des roten Kreises

Das Verfahren zum Extrahieren der roten Farbe ist mühsam, beispielsweise die Maskenverarbeitung in einem bestimmten Bereich des hsv-Farbraums.

image.png

--Seiten, auf die in der Maskenverarbeitung verwiesen wird

https://note.nkmk.me/python-opencv-numpy-alpha-blend-mask/

https://www.blog.umentu.work/python-opencv3%E3%81%A7%E3%83%9E%E3%82%B9%E3%82%AF%E5%87%A6%E7%90%86%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B%EF%BC%88%E3%81%8A%E3%81%BE%E3%81%91%E3%81%82%E3%82%8A%EF%BC%89/


  def detect_red(self, im_trimming):#Nur rot extrahieren
  # ------------------------------------------------
    im = im_trimming
    im_resize = self.resize_im(im)

    #rot(H ist 0~30,150~180 Bereich ist rot)Bereiten Sie eine Maske vor
    hsv = cv2.cvtColor(im_resize, cv2.COLOR_BGR2HSV)
    lower1 = np.array([150, 30, 100]) # HSV
    upper1 = np.array([179, 255, 255]) # HSV
    img_mask1 = cv2.inRange(hsv, lower1, upper1)
    lower2 = np.array([0, 30, 100]) # HSV
    upper2 = np.array([30, 255, 255]) # HSV
    img_mask2 = cv2.inRange(hsv, lower2, upper2)

    #Kombiniere zwei rote Masken
    mask = cv2.bitwise_or(img_mask1, img_mask2)

    #Setzen Sie die Maske auf und lassen Sie nur den roten Kreis
    im_red = cv2.bitwise_and(im_resize, im_resize, mask=mask)

    if detail2 == True: #Bild zum Debuggen speichern
      cv2.imwrite(self.path_project + self.ImName + "_red.jpg ",  im_red)
    return im_red



Kreiserkennung

Die Kreiserkennung wird für das nur rot extrahierte Bild durchgeführt. Wenn Sie beim Festlegen der Bedingungen einen Fehler machen, wird jedes Muster als Kreis erkannt. Daher ist es wichtig, die Bedingungen festzulegen.

Dieses Mal wird wie bei der linearen Erkennung die Huff-Funktion verwendet.

http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_houghlines/py_houghlines.html

detect_circle.py


 
 
  def detect_circle(self, im_trimming):#Holen Sie sich die Position des Kreises
  # ---------------------------------------------------
    # parameter
    minD = self.nomalization(58)
    p2= self.nomalization(12)
    minR = self.nomalization(30)
    maxR = self.nomalization(36)
    Lx0 = self.nomalization(10)
    Ly0 = self.nomalization(86)
    Lx = self.nomalization(90)
    Ly = self.nomalization(72)
  
    #Erkennen Sie einen Kreis aus dem rot extrahierten Bild.
    im_red = self.detect_red(im_trimming)
    im_gray = cv2.cvtColor(im_red,cv2.COLOR_BGR2GRAY)
  
    #Stellen Sie die Größe des zu erkennenden Kreises vor und nach der Größe des Kreises basierend auf der Anzahl der Pixel ein
    circles = cv2.HoughCircles(im_gray, 
                               cv2.HOUGH_GRADIENT, 
                               dp=1, 
                               minDist = minD, #Intervall pro Kreis, um die Erkennung zu ermöglichen
                               param1=1,
                               param2=p2, #Erkennungsschwelle
                               minRadius=minR, #Minimaler zu erkennender Radius
                               maxRadius=maxR) #Maximal zu erkennender Radius
  

Alle Codes

kaiseki.py



# coding: utf-8
#Digitalisieren Sie die Trefferfotos im Bewertungsbuch
# ________________________________
#Benutzereinstellungen ausgeben"True"or"False"
detail1 = True
detail2 = True
# 1 =Bild zur Bestätigung
# 2 =Bild zur Parametereinstellung
# ________________________________
 
 
#Importliste
import numpy as np
from numpy.linalg import solve
import os
import cv2
import sys
import pandas as pd
import openpyxl as excel
from pandas import ExcelWriter
import matplotlib.pyplot as plt
 
#Funktioniert mit Google Drive
from google.colab import drive
drive.mount('/content/drive')
 
#Pfadliste
path_Now_Projects = 'drive/My Drive/OU_kyudo/Now_Projects/'
path_Past_Projects = 'drive/My Drive/OU_kyudo/Past_Projects/'
 
#Erstellen Sie einen Ordner
def make_folder(path):
  if os.path.exists(path)==False:
    os.mkdir(path)
make_folder(path_Now_Projects)
make_folder(path_Past_Projects)
 
#Holen Sie sich den Bildnamen
files = []
for filename in os.listdir(path_Now_Projects):
  if os.path.isfile(os.path.join(path_Now_Projects, filename)): #Holen Sie sich nur Dateien
    files.append(filename)
if len(files)==0:
  print("Nun das Bild_Legen Sie es in den Ordner Projekte.")
  sys.exit()
 
 
 
#=============================
#<<<<<<  C l a s s  >>>>>>>>>>
 
class Tekichu(object): #initialisieren.
  # --------------------------------
  def __init__(self):
    #Bildname (mit Erweiterung)
    self.FileName = ""
    #Bildname (ohne Erweiterung)
    self.ImName, self.ext =  "",""
    #Projektname und Pfadname
    self.project = ""
    self.path_project = ""
    #Anzahl der Pixel in horizontaler Richtung des Bildes
    self.x_pixel = 1800
 
 
 
  def set_variable(self, file): #Legen Sie den Namen des Bildes fest
  # ----------------------------------------------------
    
    #Projektname und Pfadname
    self.project = input("Bild("+  file  +") Geben Sie den Projektnamen ein: ")
    self.path_project = "drive/My Drive/OU_kyudo/Now_Projects/" + self.project +"/"
    #Erstellen Sie einen Ordner mit dem Projektnamen
    if os.path.exists(self.path_project)==False:
      os.mkdir(self.path_project)
   
    #Bildname (mit Erweiterung)
    self.FileName = file
    #Bildname (ohne Erweiterung)
    self.ImName, self.ext =  os.path.splitext(file)
 
  #Normalisieren Sie Parameter, die mit Pixeln schwanken, mithilfe von Referenzwerten
  def nomalization(self, val):
    return int(self.x_pixel *(val / 1200))
 
 
 
  def resize_im(self, im): #Feste Bildgröße
  # --------------------------------------------
    size = self.x_pixel
    h, w, c = im.shape
    width,height = size, round(size * ( h / w ))
    im_resize = cv2.resize(im,(width, height))
    return im_resize
 
  
  def detect_line(self): #Frames erkennen
  # -----------------------------------------
    im = cv2.imread(path_Now_Projects + self.FileName)
    im_resize = self.resize_im(im)
    # parameter
    G = 1 + 2 * self.nomalization(10)
    T1 = 1 + 2 * self.nomalization(7)
    T2 = 1 + 2 * self.nomalization(2)
  
    #Bild verarbeiten (Rauschunterdrückung, Unschärfe, Binarisierung)
    im_denoise = cv2.fastNlMeansDenoising(im_resize)
    im_gray = cv2.cvtColor(im_denoise, cv2.COLOR_BGR2GRAY)
    im_gau = cv2.GaussianBlur(im_gray,(G,G),0)
    im_th = cv2.adaptiveThreshold(im_gau, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY,T1,T2)
    if detail2 == True:
      cv2.imwrite(self.path_project + self.ImName + "_th.jpg ", im_th)
    #Extrahieren Sie eine gerade Linie.
    imgEdge = cv2.Canny(im_th,50,150,apertureSize = 3) #Kantenerkennung nach Canny-Methode
    minLineLength = self.nomalization(200) #Schwellenwert für die Länge der zu erkennenden geraden Linie (abhängig von der Anzahl der Pixel)
    maxLineGap = self.nomalization(20) #Der längste Abstand zwischen geraden Linien, der als durchgehend angesehen werden kann (abhängig von der Anzahl der Pixel)
    th = self.nomalization(50)
    lines = cv2.HoughLinesP(imgEdge,2,np.pi/180,th,minLineLength=minLineLength,maxLineGap=maxLineGap) #Erkennung von Geraden durch Huff-Näherung
    #Wählen Sie die geraden Linien des Rahmens aus, während Sie die geraden Linien in Blau zeichnen.
    im_line = im_resize
    frame_left,frame_under, frame_over, frame_right = [10000]*4,[1]*4, [10000]*4, [1]*4 #Anfangswerteinstellung
    #Zeichnen Sie alle geraden Linien
    for i in range(len(lines)):
      for x1,y1,x2,y2 in lines[i]:
        cv2.line(im_line,(x1,y1),(x2,y2),(255,0,0),2)
    
        #Sortieren der geraden Linien des Rahmens
        if frame_left[0] > x1 and abs(y1-y2) >3*abs(x1-x2) : #Vertikale Linie mit der kleinsten x-Koordinate
          frame_left = [x1,y1,x2,y2]
        if frame_under[1] < y1 and 3*abs(y1-y2) < abs(x1-x2) : #Horizontale Linie mit der größten y-Koordinate
          frame_under = [x1,y1,x2,y2]
        if frame_over[1] > y1 and 3*abs(y1-y2) < abs(x1-x2) : #Horizontale Linie mit der kleinsten y-Koordinate
          frame_over = [x1,y1,x2,y2]
        if frame_right[0]  < x1 and abs(y1-y2) >3*abs(x1-x2) : #Vertikale Linie mit der größten x-Koordinate
          frame_right = [x1,y1,x2,y2]
    #Zeichnen Sie eine gerade Linie, die den Rahmen in Grün anzeigt.
    cv2.line(im_line,(frame_left[0], frame_left[1]),(frame_left[2], frame_left[3]),(0,255,0),2)
    cv2.line(im_line,(frame_under[0], frame_under[1]),(frame_under[2], frame_under[3]),(0,255,0),2)
    cv2.line(im_line,(frame_over[0], frame_over[1]),(frame_over[2], frame_over[3]),(0,255,0),2)
    cv2.line(im_line,(frame_right[0], frame_right[1]),(frame_right[2], frame_right[3]),(0,255,0),2)
  
    if detail2 == True: #Speichern Sie das Image zum Debuggen.
      cv2.imwrite(self.path_project + self.ImName + "_line.jpg ", im_line)
    return frame_left, frame_under, frame_over, frame_right
 
 
  
  def cross_point(self, p1, p2): #Ableitung des Schnittpunkts zweier gerader Linien, die durch zwei Punkte verlaufen
  # -----------------------------------------------------------
    return solve( [ solve(p1,[1,1]), solve(p2,[1,1]) ], [1,1] )
 
 
  
  def get_4point(self, f_under, f_left,f_over,f_right):#Erhalten Sie 4 Schnittpunkte von 4 geraden Linien, die durch 2 Punkte verlaufen
  # ------------------------------------------------------------------------------------
    f_under = np.array([f_under[0:2], f_under[2:4]])
    f_left = np.array([f_left[0:2], f_left[2:4]])
    f_over = np.array([f_over[0:2], f_over[2:4]])
    f_right = np.array([f_right[0:2], f_right[2:4]])
    UL = self.cross_point(f_under, f_left)
    OL = self.cross_point(f_over , f_left)
    UR = self.cross_point(f_under, f_right)
    OR = self.cross_point(f_over, f_right)
    return  [OL, OR, UL, UR]
 
 
  
  def transform_by4(self, points):#Schneiden Sie von 4 beliebigen Punkten zu einem Rechteck
  # --------------------------------------------------------------
    im = cv2.imread(path_Now_Projects + self.FileName)
    im_resize = self.resize_im(im)
    points = sorted(points, key=lambda x:x[1])  #Sortieren Sie in aufsteigender Reihenfolge von y.
    top = sorted(points[:2], key=lambda x:x[0])  #Die ersten beiden sind auf dem Platz. Sie können auch links und rechts sehen, indem Sie nach x sortieren.
    bottom = sorted(points[2:], key=lambda x:x[0], reverse=True)  #Die beiden letzteren befinden sich unterhalb des Quadrats. Auch sortiert nach x.
    points = np.array(top + bottom, dtype='float32')  #Verbinden Sie die beiden getrennten Teile wieder.
    width = max(np.sqrt(((points[0][0]-points[2][0])**2)*2), np.sqrt(((points[1][0]-points[3][0])**2)*2))
    height = max(np.sqrt(((points[0][1]-points[2][1])**2)*2), np.sqrt(((points[1][1]-points[3][1])**2)*2))
    dst = np.array([
      np.array([0, 0]),
      np.array([width-1, 0]),
      np.array([width-1, height-1]),
      np.array([0, height-1]),
      ], np.float32)
    trans = cv2.getPerspectiveTransform(points, dst)  #Wenn Sie die Entsprechung zwischen den Koordinaten vor der Konvertierung und den Koordinaten nach der Konvertierung übergeben, wird eine perspektivische Konvertierungsmatrix erstellt.
    im_trimming = cv2.warpPerspective(im_resize, trans, (int(width), int(height)))  #Zuschneiden mit einer perspektivischen Transformationsmatrix.
    
    if detail2 == True:
      cv2.imwrite(self.path_project +  self.ImName +'_trimming.jpg', im_trimming)
    return im_trimming
 
 
 
  
  def detect_red(self, im_trimming):#Nur rot extrahieren
  # ------------------------------------------------
    im = im_trimming
    im_resize = self.resize_im(im)
  
    #rot(H ist 0~30,150~180 Bereich ist rot)Bereiten Sie eine Maske vor
    hsv = cv2.cvtColor(im_resize, cv2.COLOR_BGR2HSV)
    lower1 = np.array([150, 30, 100]) # HSV
    upper1 = np.array([179, 255, 255]) # HSV
    img_mask1 = cv2.inRange(hsv, lower1, upper1)
    lower2 = np.array([0, 30, 100]) # HSV
    upper2 = np.array([30, 255, 255]) # HSV
    img_mask2 = cv2.inRange(hsv, lower2, upper2)
  
    #Kombiniere zwei rote Masken
    mask = cv2.bitwise_or(img_mask1, img_mask2)
  
    #Setzen Sie die Maske auf und lassen Sie nur den roten Kreis
    im_red = cv2.bitwise_and(im_resize, im_resize, mask=mask)
  
    if detail2 == True: #Bild zum Debuggen speichern
      cv2.imwrite(self.path_project + self.ImName + "_red.jpg ",  im_red)
    return im_red
 
 
 
  def detect_circle(self, im_trimming):#Holen Sie sich die Position des Kreises
  # ---------------------------------------------------
    # parameter
    minD = self.nomalization(58)
    p2= self.nomalization(12)
    minR = self.nomalization(30)
    maxR = self.nomalization(36)
    Lx0 = self.nomalization(10)
    Ly0 = self.nomalization(86)
    Lx = self.nomalization(90)
    Ly = self.nomalization(72)
  
    #Erkennen Sie einen Kreis aus dem rot extrahierten Bild.
    im_red = self.detect_red(im_trimming)
    im_gray = cv2.cvtColor(im_red,cv2.COLOR_BGR2GRAY)
  
    #Stellen Sie die Größe des zu erkennenden Kreises vor und nach der Größe des Kreises basierend auf der Anzahl der Pixel ein
    circles = cv2.HoughCircles(im_gray, 
                               cv2.HOUGH_GRADIENT, 
                               dp=1, 
                               minDist = minD, #Intervall pro Kreis, um die Erkennung zu ermöglichen
                               param1=1,
                               param2=p2, #Erkennungsschwelle
                               minRadius=minR, #Minimaler zu erkennender Radius
                               maxRadius=maxR) #Maximal zu erkennender Radius
    circle_position = [[0 for i in range(20)] for j in range(13)]
    total_number = [0 for i in range(13)]
    warning = False
    if circles is not None:
      circles = circles.squeeze(axis=0) #Holen Sie sich den Mittelpunkt des Kreises
      im_circle = self.resize_im(im_trimming)
   
      #Parameter gemäß dem Raster des Bewertungsbuchs
      x_level = [int(Lx0+i*Lx) for i in range(13)]
      y_level = [int(Ly0+j*Ly) for j in range(21)]
      #Zeichne alle Gitter
      for i in x_level: 
        cv2.line(im_circle,(i, 0),(i, int(self.x_pixel * 9/16)),(0,0,255),1)
      for j in y_level:
        cv2.line(im_circle,(0, j),(self.x_pixel, j),(0,0,255),1)
    
      #Ordnen Sie die Mittelposition des Kreises an, indem Sie ihn mit dem Raster vergleichen
      for cx, cy, r in circles:     
        #Zeichnen Sie den Umfang und den Mittelpunkt des Kreises.
        cv2.circle(im_circle, (cx, cy), r, (0, 255, 0), 2)
        cv2.circle(im_circle, (cx, cy), 2, (0, 255, 0), 2)
    
        horizontal = int((cx-Lx0) // Lx)
        vertical = int((cy-Ly0)// Ly)
    
        #Wenn sich der Kreis über das Gitter hinaus erstreckt, werden Anomalien erkannt und behoben.
        if vertical >= 20:
          vertical = 19
          warning = True
      
        #In Array aufnehmen
        circle_position[horizontal][vertical] += 1  
    
        #Zeichnen Sie Anomalien auf, wenn zwei oder mehr in einem Raster erkannt werden
        if circle_position[horizontal][vertical] >= 2:
          warning = True
    
    if detail1 == True:
      cv2.imwrite(self.path_project + self.ImName + "_circles.jpg ", im_circle)
  
    #Gesamttreffer berechnen
    for i in range(13):
      total_number[i] = np.sum(circle_position[i])
   
    #Textifizierung
    for i in range(13):
      for j in range (20):
        if circle_position[i][j] == 1:
          circle_position[i][j] = "○"
        elif circle_position[i][j] == 0:
          circle_position[i][j] = "・"
    
    #Beitreten
    data = np.r_[np.array([total_number]), np.array(circle_position).T] #Kombinieren Sie so, dass die Summe die 0. Zeile und der Treffer die 1. bis 20. Zeile ist
    df = pd.DataFrame(data) 
  
    #Ergebnisse anzeigen
    if warning == True :
      print("[Warnung] Das Ergebnis enthält einen Fehler."+ self.FileName)
    print(df)
    return df
 
  
  def tekichu_main(self):#Hauptprogramm im Unterricht
  # ------------------------------------------------
    f_left, f_under , f_over, f_right = self.detect_line()
    box_points = self.get_4point(f_left, f_under , f_over, f_right)
    im_trimming = self.transform_by4(box_points)
    df = self.detect_circle(im_trimming)
    wb = excel.Workbook() #Erstellen Sie eine neue Arbeitsmappe
    wb.save(self.path_project + self.project +".xlsx")
    writer = ExcelWriter(self.path_project + self.project + '.xlsx')
    df.to_excel(writer, sheet_name = self.ImName) #Schreiben Sie in Excel
    writer.save()
    return df
 
 
 
#==================================
#>>>Hauptprogramm>>>>>>>>>>>>>>>
if __name__ == '__main__':
  for i in range(len(files)):
    tek1 = Tekichu()
    tek1.set_variable(files[i])
    df = tek1.tekichu_main()
  print("Normal beendet")


Ausführungsverfahren

Ich wollte es wirklich mit einem richtig aufgenommenen Bild analysieren

Aber es war unmöglich.

Um die Position des Treffer-Kreises zu analysieren, ist es notwendig, die Positionsbeziehung des Gitters im Bewertungsbuch zu verstehen.

Ich habe eine lineare Erkennungsfunktion verwendet, um sie zu erkennen, aber ...

Wenn ein Hintergrund vorhanden ist, wird dieser auf unvorhersehbare Weise erkannt. Wie erwartet kann dies nicht geholfen werden.

⇒ Lassen Sie das Bild so zuschneiden, dass der Hintergrund nicht eintritt

trimming.png

Unter dieser Bedingung haben wir es ermöglicht, eine stabile Analyse durchzuführen.

Antriebsvorbereitung

Erstellen Sie aufgrund der Spezifikationen dieses Programms zunächst einen Ordner mit dem Namen "kyudo" und zwei Ordner mit den Namen "New_Projects" und "Past_Projects".

Platzieren Sie das zugeschnittene Bild dort, da es für die Verarbeitung des in "New_Projects" enthaltenen Bilds ausgelegt ist.

ドライブ用意.png

Schaltfläche ausführen, wenn fertig! Das dreht sich um ...

Ich wurde angewiesen, das Laufwerk zu mounten. Wenn Sie Google Collab zum ersten Mal öffnen

Wenn Sie mit dem Mounten des Laufwerks noch nicht vertraut sind, sollten Sie es lesen.

Wenn Sie es wissen, überspringen Sie es bitte.

ドライブマウント1.png

Wählen Sie nun Ihr Konto aus.

ドライブマウント2.png

Damit ist die Montage abgeschlossen. Geben Sie dann den Projektnamen ein.

Wenn Sie es nach Eingabe des Projektnamens ausführen, wird das Analyseergebnis angezeigt und die Daten in der Tabelle werden im Laufwerk gespeichert.

Es war besser, den Benutzer einen Teil davon auf dem GUI-Bildschirm verarbeiten zu lassen

Danach schrieb ich den Code für die Verarbeitung mit GUI (grafische Benutzeroberfläche) unter Verwendung von Tkinter ohne Verwendung von Google Colab, aber das war in Bezug auf Genauigkeit und Betrieb besser.

Nun, das war eine Lernerfahrung und ich habe es genossen.

Recommended Posts

Ich habe versucht, das Bild des Bogenschießen-Bewertungsbuchs (eine Broschüre, in der die Ergebnisse von Treffern aufgezeichnet werden) zu analysieren. (Google Colaboratory)
Ich habe einen Korpusleser geschrieben, der die Ergebnisse der MeCab-Analyse liest
Eine Geschichte, die die Lieferung von Nico Nama analysierte.
Ich habe einen Kalender erstellt, der den Verteilungsplan von Vtuber automatisch aktualisiert (Google Kalender Edition).
Ich habe ein Punktbild des Bildes von Irasutoya gemacht. (Teil 1)
Ich habe ein Punktbild des Bildes von Irasutoya gemacht. (Teil 2)
Ich habe ein Skript geschrieben, das das Bild in zwei Teile teilt
Ich habe einen Linienbot erstellt, der das Geschlecht und das Alter einer Person anhand des Bildes errät
Ich habe einen schlaffen Bot gemacht, der mich über die Temperatur informiert
Eine Geschichte, die die elektronische Bewertung von Prüfungen mit Bilderkennung unterstützt
So führen Sie den Übungscode des Buches "Profitable KI mit Python erstellen" in Google Colaboratory aus
Ich habe versucht, die Abstimmungsergebnisse der Metropolregion Osaka für jede Gemeinde zu analysieren
Ich habe einen Kalender erstellt, der den Verteilungsplan von Vtuber automatisch aktualisiert
Ich habe versucht, die Trefferergebnisse von Hachinai mithilfe der Bildverarbeitung zu erhalten
Aus einem Buch, das die Denkweise des Programmierers interessanterweise gelernt hat (Python)
Klasse, die die API von DMM trifft
Ich habe einen LINE BOT erstellt, der mithilfe der Flickr-API ein Bild von Reis-Terroristen zurückgibt
Rund um die Authentifizierung von PyDrive2, einem Paket zum Betreiben von Google Drive mit Python
Die Geschichte der Erstellung einer Webanwendung, die umfangreiche Lesungen mit Django aufzeichnet
[Python] Ein Programm, das die Anzahl der Aktualisierungen der höchsten und niedrigsten Datensätze berechnet
[Bot dekodieren] Ich habe versucht, einen Bot zu erstellen, der mir den Rassenwert von Pokemon angibt
Ich möchte einen Slack-Bot, der das Gehalt eines Teilzeitjobs aus dem Zeitplan von Google Kalender berechnet und anzeigt!