Automatische Detektion von Meteor Scatter Spektrogrammen

Hallo Wilhelm,

Am 10. war meine Anlage ausgerechnet aus…Wenn der Stick die Woche durchhält, würde ich nach meinem Urlaub auf 3D Umstellen und wenn du nichts dagegen hast, dein Modell (allerdings für Windows 10) nutzen. Der Juni naht aber ich bin langsam auf dem richtigen Weg :)

Beste Grüße
Stefanie
 
Hallo Stefanie,
ja, ich würde mich freuen, wenn du mein Programm benutzt.
Das Model, eine 250 KB große .h5 Datei, kann man vermutlich hier nicht anhängen. Die müsste ich dir und anderen Interessenten per Mail schicken.

Gut, dass du mich an die Arietiden erinnerst: Dazu muss ich mir noch Gedanken über die Stromversorgung auf unserem Modellflugplatz machen.

Die Daten von heute geben nicht viel her. Der blaue Pfeil zeigt, wo die Blitze geloggt wurden.

Einen schönen Abend wünsche ich Euch,
viele Grüße
Wilhelm
 

Anhänge

  • April11-a.png
    April11-a.png
    311,7 KB · Aufrufe: 78
Zuletzt bearbeitet:
Sorry, das Modell ist 250 MB groß.
Unten in dem Ordner wurde auf der RTX 3060 Grafikkarte im i5 Notebook trainiert, oben auf einem normalen i5 Notebook.
 

Anhänge

  • I5-vs-RTX3060-Faktor35.jpg
    I5-vs-RTX3060-Faktor35.jpg
    605,5 KB · Aufrufe: 44
Guten Morgen,

Ich hatte mich schon gewundert 😂 Danke, ich bräuchte auch noch die die komplette env, falls du conda nutzt, kann man das requirements.txt exportieren. Die Modelle lassen sich oft nicht nutzen, wenn die Versionen einer Bibliotheken nicht übereinstimmen…

Beste Grüße
Stefanie

P.S. Ich könnte daraus ein pip Paket bauen, dann kann man es mittels „pip install wilhelms_meteor_detection“ oder so ähnlich direkt installieren (falls es öffentlich werden soll).
 
Hallo Stefanie,
danke für deine Anregungen.

Zu den Arietiden:
Eine Meteor-Anlage wird ganz normal hier zu Hause loggen. Mit der zweiten Anlage will ich nur die Zeit rund um die Kerbe in störungsfreier Umgebung aufnehmen. Das Problem ist, dass mein Notebook 19 V benötigt und das Powersupply soll natürlich keine Störungen produzieren.
Vielleicht teste ich mal eine 19 V Auto-PC-Stromversorgung. Die 12 V für den RX kann ich direkt von der Autobatterie nehmen.
Beim Fliegen und Laden der Akkus am Platz hatte ich schon den Fall, dass der Wagen nachher nicht mehr ansprang…
Ich bin auch noch in einem zweiten Verein mit Hütte und Stromversorgung. Aber mitten im Sommer zur besten Flugzeit laufen dort die Ladegeräte.

Zur Software:
Conda benutze ich nicht. Du / Ihr braucht Python und die Pixellib-Installation, wie ich es neulich beschrieben habe. Die Installation der Nvidia Software dokumentiere ich später noch mal.

Ich stelle alles zur Verfügung, auch die Bilder fürs Training und die Labeldaten. Wenn du Zeit hast, kannst du daraus eine Umgebung bauen, vielleicht bei Github, die sich jeder installieren kann.
Meine Python Software besteht aus drei Programmen:
Training und Auswertung mit Pixellib und ein Plot- und Filterprogramm.
Das Trainingsprogramm ist das Original-Programm von der Pixellib Autorin Ayoola Olafenwa.
Beim Filterprogramm weis ich allerdings noch gar nicht, wie das (Meta)-Datenformat aussehen soll.

Wenn du Interesse hast, stelle ich die ersten beiden Programme hier rein, würde aber vorher noch etwas Kommentar reinschreiben.

Der Meteor ist von heute, 4:20 h UT.

Einen schönen Tag wünsche ich Euch,
viele Grüße
Wilhelm
 

Anhänge

  • GRAVES-XYmVV_230412041959.jpg
    GRAVES-XYmVV_230412041959.jpg
    596,2 KB · Aufrufe: 43
  • test-final.png
    test-final.png
    956,4 KB · Aufrufe: 41
Zuletzt bearbeitet:
Hallo Wilhelm,

Du nutzt ja sicher pip und könntest dann stattdessen die freeze Funkion nutzen : pip freeze - pip documentation v23.0.1

Daraus kann ich dann sehr einfach ein Package erstellen. Code wäre natürlich super, ich bastel dann eine GitHub Seite und submitte zu pip wenn du einverstanden bist.

Schönen Meteor hast du da eingefangen 👍👍👍

Viele Grüße aus dem sonnigen Spanien
Stefanie
 
Hallo Stefanie,
dankeschön. Gestern Abend war auch noch ein interessanter dabei.
Die Sache mit pip freeze überblicke ich nicht. Du kannst das so machen, wie du das für richtig hältst. Aber genieße erst mal den Urlaub.

Im nächsten Post zeige ich die momentanen Versionen.
Basis ist Pixellib von Ayoola Olafenwa. Das Auswerteprogramm ist noch in Arbeit. Das Trainingsprogramm ist 1:1 aus dem Tutorial.

Ich müsste auch noch mehr labeln, aber es funktioniert so schon ganz ordentlich.
Viele Grüße
Wilhelm
 

Anhänge

  • GRAVES-XYmVV_230412223140.jpg
    GRAVES-XYmVV_230412223140.jpg
    600,4 KB · Aufrufe: 41
  • test-final.png
    test-final.png
    947,3 KB · Aufrufe: 44
Auswerteprogramm:
Code:
# (C) WiSi-Testpilot, letzte Anderung: 12.4.2023
# cd C:\Users\Wilsi\Desktop\k3

import glob
import time
import math as m
import random
import datetime
import numpy as np
import cv2
import pixellib
import tensorflow as tf
from shapely.geometry import Polygon

startzeit = datetime.datetime.now()

print("################### Num GPUs Available: ", len(tf.config.list_physical_devices('GPU')))

from pixellib.instance import custom_segmentation
segment_image = custom_segmentation()
segment_image.inferConfig(num_classes= 3, class_names= ["BG", "Artifical-Star", "Background", "Meteor"])
segment_image.load_model("C:/Users/Wilsi/Desktop/k3/drei-Klassen/mask_rcnn_model.068-0.405656.h5")

#>>>>>>>>>>>>>>>>> hier ein paar Startwerte eingeben
sname =  " mask_rcnn_model.068-0.405656 "
debug = 1   # 0: normal, 1: Einzelschritt, 2: stoppt bei Score unter 0.8, 3: stoppt bei Starlink
Aufnahmejahr = " 2023,"
path = glob.glob("C:/Users/Wilsi/Desktop/GRAVE*.jpg")

bg = np.zeros((550, 1900, 3), np.uint8)            # Output Display
summe_3min = np.zeros((481), np.uint32)
fsumme_3min = np.zeros((481), np.single)

histogramm = np.zeros((540, 510, 3), np.uint8)    #Histogramm Display
summe_fl   = np.zeros((26), np.single)
summe_anz  = np.zeros((26), np.uint32)

score_100_99 = 0
score_99_98 = 0
score_98_97 = 0
score_97_96 = 0
score_96_95 = 0
score_95_94 = 0
score_94_93 = 0
score_93_90 = 0
score_90_80 = 0
score_80_70 = 0
score_70_00 = 0

Baseline = 700
kleiner_Baseline = 0
kleiner_Baseline_alle = 0
plot_count = 0
globalcount = 0
Art_count = 0
BG_count = 0
Err_count = 0
RED = (0, 0, 255)
noisefloor = 1
fontScale = 0.6
fthickness = 1
font = cv2.FONT_HERSHEY_SIMPLEX
WHITE = (200, 200, 200)

for fname in path:                      # Analyse über alle Files im Pfad
    print(' > ', fname)
    position = fname.find(".jpg")       # Zeit und Datum werden aus dem Filenamen extrahiert
    zeit = fname[position-10:position]
    print ("Jahr Monat Tag St. Min. Sek.", '20' + fname[position-12:position])
    monat= zeit[0:2]
    if monat == '01': Monat = 'Januar'
    if monat == '02': Monat = 'Februar'
    if monat == '03': Monat = 'Maerz'
    if monat == '04': Monat = 'April'
    if monat == '05': Monat = 'Mai'
    if monat == '06': Monat = 'Juni'
    if monat == '07': Monat = 'Juli'
    if monat == '08': Monat = 'August'
    if monat == '09': Monat = 'September'
    if monat == '10': Monat = 'Oktober'
    if monat == '11': Monat = 'November'
    if monat == '12': Monat = 'Dezember'
    day= zeit[2:4]
    ho = zeit[4:6]    # Zeit aus Filenamen extrahieren
    mi = zeit[6:8]
    se = zeit[8:10]
 #  print('Monat: ', monat)
 #  print('Tag: ', day)
 #  print (day + '.', Monat, '2023')
    ctime = (float(ho) * 3600 ) + (float(mi) *60) + float(se)   # X-Position aus Zeit berechnen
 #  print('################# ctime  ', round(ctime), '   ', round(ctime/20), '   ', round(ctime/180))
    xa = round (ctime / 60)
    if (mi == '00') and ((se == '00') or (se == '59') or (se == '01') ):
        bg = cv2.line(bg,(xa,500),(xa, 515), WHITE, 2)      # X ganze Stunden-Ticks
        org = (xa, 530)  # war 535
        bg = cv2.putText(bg, ho, org, font, fontScale, WHITE, fthickness, cv2.LINE_AA)

    if ((mi == '30') or (mi == '15') or (mi == '45')) and ((se == '00') or (se == '59') or (se == '01') ):
        bg = cv2.line(bg,(xa,500),(xa, 510), WHITE, 1)        # X 1/4 Stunden-Ticks


    RED = (0, 0, 255)  # b g r
    GREEN = (20, 255, 20,)
    YELLOW = (0, 255, 255)
    BLUE = (255, 0, 0)
    Magenta = (147, 20, 255)
    DarkOrange = (15, 185, 255)  # Gold
    WHITE = (200, 200, 200)
    Gray = (100, 100, 100)
    light_BLUE = (255, 191, 0)
    DarkOrange1 = (0, 140, 255)  # alt
    lite_MAGENTA = (255, 0, 255)
    Rose = (200, 200, 255)
    lRED = (20, 20, 200)  # b g r
    OrangeRed = (0, 190, 255)  # b g r fast gelb
    darkOlive = (40, 120, 40)
    Olive = (150, 255, 150)

    isClosed = True
    dicke = 3
    radius = 4
    org = (0, 0)

    paare         = np.zeros((1000,2), np.int32)

    bg_RED        = np.zeros((1000,2), np.int32)
    bg_GREEN      = np.zeros((1000,2), np.int32)
    bg_YELLOW     = np.zeros((1000,2), np.int32)
    bg_BLUE       = np.zeros((1000,2), np.int32)
    bg_Magenta    = np.zeros((1000,2), np.int32)
    bg_DarkOrange = np.zeros((1000,2), np.int32)
    bg_WHITE      = np.zeros((1000,2), np.int32)
 
    bg_light_BLUE   = np.zeros((1000,2), np.int32)
    bg_DarkOrange1  = np.zeros((1000,2), np.int32)
    bg_lite_MAGENTA = np.zeros((1000,2), np.int32)
    bg_Rose         = np.zeros((1000,2), np.int32)
    bg_lRED         = np.zeros((1000,2), np.int32)
    bg_OrangeRed    = np.zeros((1000,2), np.int32)
    bg_darkOlive    = np.zeros((1000,2), np.int32)
    bg_Olive        = np.zeros((1000,2), np.int32)


    box_RED         = np.zeros((4), np.int32)
    box_GREEN       = np.zeros((4), np.int32)
    box_YELLOW      = np.zeros((4), np.int32)
    box_BLUE        = np.zeros((4), np.int32)
    box_Magenta     = np.zeros((4), np.int32)
    box_DarkOrange  = np.zeros((4), np.int32)
    box_WHITE       = np.zeros((4), np.int32)

    box_light_BLUE   = np.zeros((4), np.int32)
    box_DarkOrange1  = np.zeros((4), np.int32)
    box_lite_MAGENTA = np.zeros((4), np.int32)
    box_Rose         = np.zeros((4), np.int32)
    box_lRED         = np.zeros((4), np.int32)
    box_OrangeRed    = np.zeros((4), np.int32)
    box_darkOlive    = np.zeros((4), np.int32)
    box_Olive        = np.zeros((4), np.int32)

    summe_RED = 0
    summe_GREEN = 0
    summe_YELLOW = 0
    summe_BLUE = 0
    summe_Magenta = 0
    summe_DarkOrange = 0
    summe_WHITE = 0

    summe_light_BLUE = 0
    summe_DarkOrange1 = 0 
    summe_lite_MAGENTA = 0
    summe_Rose = 0 
    summe_lRED = 0
    summe_OrangeRed = 0
    summe_darkOlive = 0
    summe_Olive = 0

    anz_RED = 0
    anz_GREEN = 0
    anz_YELLOW = 0
    anz_BLUE = 0
    anz_Magenta = 0
    anz_DarkOrange = 0
    anz_WHITE = 0

    anz_light_BLUE = 0
    anz_DarkOrange1 = 0 
    anz_lite_MAGENTA = 0
    anz_Rose = 0 
    anz_lRED = 0
    anz_OrangeRed = 0
    anz_darkOlive = 0
    anz_Olive = 0

    # Bild wird analysiert
    segmask, output = segment_image.segmentImage (fname, mask_points_values=True, show_bboxes=True)  #, output_image_name="2-testy.jpg")
    print ('    rois')
    a = segmask.get('rois')
    print (a)
    print (len(a))
    print ('    class_ids')
    # Noise Floor auswerten
    if len(a) == 0:
        nfmittelwert = 0.0
        if noisefloor == 1:
            for i_nf in range (300, 401):
                for j_nf in range (200, 301):
                    for k_nf in range (0, 3):
                        nfmittelwert = nfmittelwert + output[i_nf, j_nf, k_nf]
            cv2.circle(bg, (xa, 500 - int(nfmittelwert/5000)), 1 , Magenta, -1)
      #      Debugg Noisefloor
      #      print (nfmittelwert/5000)
      #      cv2.rectangle(output, (300, 200), (400, 300), YELLOW, 2)
      #      cv2.imshow("Bild fuer NF", output)
      #      cv2.waitKey(0)
      #      cv2.destroyAllWindows()

    #b = segmask.get('class_ids')
    b = segmask['class_ids'].astype('int')
    print (b)
    print (len(b))
    test  = np.zeros((100), np.int32)
    for itest in range (0, len(b)):
        test[itest] = b[itest]
        print (test[itest]*10)

    print ('    scores')
    c = segmask.get('scores')
    print (c)
    print (len(c))
    if len(c) > 0:
        print ('----masks')
        if len(b) > 1:  d = segmask.get('masks')
        if len(b) == 1:
            try:
                d = segmask['masks'].astype('int')
                print ('################################## len(b) war 1 ')
            except:
                d = segmask.get('masks')
     #  print('*********')
        print (len(d))
     #  print(d)
        anzahl = 0
        anzahl = len(d)
        print ('Anzahl Objekte  ', anzahl)

####### Konturen werden ausgewertet
        counter = 0
        color = Olive
    #   for i in d: cv2.polylines(output, i, isClosed, light_BLUE, dicke)
        for i in d:
            counter += 1
            print('#############   ', b[counter -1])
            if counter == 1:
                color = RED
                bg_RED  = i
            if counter == 2:
                color = GREEN
                bg_GREEN  = i
            if counter == 3:
                color = YELLOW
                bg_YELLOW  = i
            if counter == 4:
                color = BLUE
                bg_BLUE  = i
            if counter == 5:
                color = Magenta
                bg_Magenta  = i
            if counter == 6:
                color = DarkOrange
                bg_DarkOrange  = i
            if counter == 7:
                color = WHITE
                bg_WHITE  = i   
 
            if counter == 8:
                color =  light_BLUE
                bg_light_BLUE = i
            if counter == 9:
                color =  DarkOrange1
                bg_DarkOrange1 = i
            if counter == 10:
                color = lite_MAGENTA
                bg_lite_MAGENTA = i
            if counter == 11:
                color = Rose
                bg_Rose = i
            if counter == 12:
                color = lRED
                bg_lRED = i
            if counter == 13:
                color = OrangeRed
                bg_OrangeRed = i
            if counter == 14:
                color = darkOlive
                bg_darkOlive = i
            if counter == 15:
                color = Olive
                bg_Olive = i


        print('Anzahl der Bruchstuecke ')
        print(len(bg_RED))
        print(len(bg_GREEN))
        print(len(bg_YELLOW))
        print(len(bg_BLUE))
        print(len(bg_Magenta))
        print(len(bg_DarkOrange))
        print(len(bg_WHITE))
        print(len(bg_light_BLUE))
        # hier fehlt noch 9-15
        print(' >>>>>>>>> 1000 = leer')


        for o in range (1, anzahl +1):
            if o == 1:
                bg_temp = bg_RED
                col_temp = RED
                col_name = 'RED'
            if o == 2:
                bg_temp = bg_GREEN
                col_temp = GREEN
                col_name = 'GREEN'
            if o == 3:
                bg_temp = bg_YELLOW
                col_temp = YELLOW
                col_name = 'YELLOW'
            if o == 4:
                bg_temp = bg_BLUE
                col_temp = BLUE
                col_name = 'BLUE'
            if o == 5:
                bg_temp = bg_Magenta
                col_temp = Magenta
                col_name = 'Magenta'
            if o == 6:
                bg_temp = bg_DarkOrange
                col_temp = DarkOrange
                col_name = 'DarkOrange'
            if o == 7:
                bg_temp = bg_WHITE
                col_temp = WHITE
                col_name = 'WHITE'
########### hier fehlt noch 8-15
          #  if test[o-1] > 1: cv2.fillPoly(output, bg_temp, col_temp)

            laenge = len(bg_temp)
            print ('  Bruchstuecke von: ', col_name, '   ', laenge)
            counter = 0
            summe = 0
            xsumme = 0
            ysumme = 0
            for ii in bg_temp:
                print ('  Anzahl Wertepaare: ', len(ii))
                paare = np.zeros((len(ii),2), np.int32)
                if len(ii) >= 3:
                    counter = 0
                    for jj in ii:
                        paare[counter] = jj
                        counter += 1
                    cv2.fillPoly(output, [paare], col_temp)
                    pgon = Polygon(paare)
                    summe += pgon.area
                    print ('  Flaeche ', col_name, '      ', pgon.area)
                    mitte_x = round(pgon.centroid.x)
                    xsumme += mitte_x
                    mitte_y = round(pgon.centroid.y)
                    ysumme += mitte_y
                    print ('  Zentrum ', col_name, '  X= ', mitte_x, '  Y= ', mitte_y)
                if len(ii) < 3:
                    print (' >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>verworfen  ')
                    laenge -= 1
            if laenge > 1:
                print (' >>>>>> Mittelwert Zentrum: ', col_name, '  Xs= ', round(xsumme / laenge), '  Ys= ', round(ysumme / laenge))
                print (' >>>>>>>> Summe der Fläche: ', summe)
 
  
########### Dopplershift berechnen         
            if laenge > 0:
                org = (round(xsumme / laenge), round(ysumme / laenge))
                Ax = 945       # Projektionslini für die Dopplerschift
                Ay = 609   
                Bx = 350
                By = 28 
                cv2.line(output, (Ax, Ay),(Bx, By), Magenta, 1)
                cv2.putText(output, ('Ax, Ay'), (Ax, Ay), font, fontScale, WHITE, fthickness, cv2.LINE_AA)

                dx = Bx - Ax
                dy = By - Ay
                cqu = dx*dx + dy*dy
                c_geo = m.sqrt(cqu)
         #      print ('  c_geo  ', c_geo)

                ux, uy = org

                dx = Bx - ux
                dy = By - uy
                a1_geo = m.sqrt(dx*dx + dy*dy)
         #      print ('  a1_geo  ',a1_geo)

                dx = Ax - ux
                dy = Ay - uy
                b1_geo = m.sqrt(dx*dx + dy*dy)
         #      print ('  b1_geo  ',b1_geo)
                try:   
                   cos_alpha = (b1_geo * b1_geo + cqu - a1_geo * a1_geo)/(2*b1_geo * c_geo) #Cosinussatz
                except:
                   cos_alpha = 0.7
         #      print ('  cos alpha  ', cos_alpha)
                try:
                    A_arc = m.acos(cos_alpha)
                except:
                    A_arc = 99
                sin_A = m.sin(A_arc)
                cos_A = m.cos(A_arc)
                A_deg = np.rad2deg(A_arc)
         #      print ('  Alpha  ',A_deg)
                hoehe1 = b1_geo * sin_A
         #      print ('  Hoehe: ', hoehe1)
                dopplershift =  round (m.sqrt(a1_geo * a1_geo - hoehe1 * hoehe1))   
                print ('  rel. Dopplershift: ', dopplershift)
############### Ende Dopplershift

                print (' >>>>>>>>>>>>>>>>>>>> Klasse: ', test[o-1])
                cv2.circle(output, org, 6 , WHITE, -1)
                if col_name == 'RED': cv2.circle(output, org, 3 , GREEN, -1)
                if col_name != 'RED': cv2.circle(output, org, 3 , RED, -1)
                fsize = ("{:5.0f}".format(summe))
                ds = ("{:3.0f}".format(dopplershift))

############ Echos im Bereich 200 bis 396 loggen. 196 (200 bis 396) entspricht 20 Sekunden in meinen Plots.
############ Ausser bei der Dopplershift ist dies der einzige Parameter. Den Wert kann man im Einzelschrittmodus ablesen.
 
                if (uy >= 200) and ( uy < 396) and (test[o-1] == 3) and (dopplershift > 300) and (dopplershift < 700) and (summe < 100000):
                    fontScale = 0.6
                    fsize = '++++++Flaeche:' + fsize + ' Dopplersh.:' + ds
                    print (' Score in Window ', c[o-1])

                    if (c[o-1] <= 1.00) and (c[o-1] > 0.99): score_100_99 += 1
                    if (c[o-1] <= 0.99) and (c[o-1] > 0.98): score_99_98 += 1
                    if (c[o-1] <= 0.98) and (c[o-1] > 0.97): score_98_97 += 1
                    if (c[o-1] <= 0.97) and (c[o-1] > 0.96): score_97_96 += 1
                    if (c[o-1] <= 0.96) and (c[o-1] > 0.95): score_96_95 += 1
                    if (c[o-1] <= 0.95) and (c[o-1] > 0.94): score_95_94 += 1
                    if (c[o-1] <= 0.94) and (c[o-1] > 0.93): score_94_93 += 1
                    if (c[o-1] <= 0.93) and (c[o-1] > 0.90): score_93_90 += 1               
                    if (c[o-1] <= 0.90) and (c[o-1] > 0.80): score_90_80 += 1
                    if (c[o-1] <= 0.80) and (c[o-1] > 0.72): score_80_70 += 1 
                    if (c[o-1] <= 0.72) and (c[o-1] > 0.00): score_70_00 += 1 
                  
                    offset_summe = summe - Baseline
                    if offset_summe <= 0:
                        offset_summe = 1
                        kleiner_Baseline_alle +=1

                    if (c[o-1] >= 0.72):  # nur hier loggen
                        y_t_color = GREEN
                        globalcount += 1                     
                        if offset_summe == 1: kleiner_Baseline += 1
                        fl = int(495 -100 * m.log10(offset_summe))
                        bg = cv2.circle(bg, (xa, fl), dicke , y_t_color, -1)
                        plot_count = round(ctime / 360)   # 180 360
                        summe_3min[plot_count] += 1
                        fsumme_3min[plot_count] = fsumme_3min[plot_count] + summe 

                        summe_anz[int(ho)+1] = summe_anz[int(ho)+1] + 1
                        summe_fl[int(ho)+1] = summe_fl[int(ho)+1] + summe

                    if debug == 2:
                        if (c[o-1] < 0.8):
                            stream = cv2.imread(fname) 
                            segmask, stream = segment_image.segmentImage (fname, mask_points_values=True, show_bboxes=True)
                            cv2.imshow("Output", stream)
                            cv2.imwrite("bad.png", stream)
                            cv2.waitKey(0)
                            stream = cv2.imread(fname)
                            cv2.imshow("Output", stream)
                            cv2.imwrite("bad-org.png", stream)
                            cv2.waitKey(0)
                      
################ Echos liegen zu nahe am Rand
                if (uy >= 200) and ( uy < 396) and (test[o-1] == 3) and ((dopplershift <= 300) or (dopplershift >= 700)):
                    fontScale = 0.6
                    fsize = '-x-W-x--Flaeche:' + fsize + ' Dopplersh.:' + ds
                    y_t_color = YELLOW
                    Err_count += 1
                    offset_summe = summe - Baseline
                    if offset_summe <= 0: offset_summe = 1
                    fl = int(495 -100 * m.log10(summe))
                    bg = cv2.circle(bg, (xa, fl), dicke , y_t_color, -1)           
                  
################ Background innerhalb der 20 Sekunden loggen
                if (uy >= 200) and ( uy < 396) and (test[o-1] == 2) and (dopplershift >= 20): # Rand weg
                    fontScale = 0.6
                    fsize = '----R---Flaeche:' + fsize + ' Dopplersh.:' + ds
                    y_t_color = RED
                    BG_count += 1
                    offset_summe = summe - Baseline
                    if offset_summe <= 0: offset_summe = 1
                    fl = int(495 -100 * m.log10(offset_summe))
                    bg = cv2.circle(bg, (xa, fl), 2 , y_t_color, -1)    # 2 = dicke       
                
################ Starlinks innerhalb der 20 Sekunden loggen
                if (uy >= 200) and ( uy < 396) and (test[o-1] == 1):
                    fontScale = 0.6
                    fsize = '----B----Flaeche:' + fsize + ' Dopplersh.:' + ds
                    y_t_color = BLUE
                    Art_count += 1
                    offset_summe = summe - Baseline
                    if offset_summe <= 0: offset_summe = 1
                    fl = int(495 -100 * m.log10(offset_summe))
                    bg = cv2.circle(bg, (xa, fl), dicke , y_t_color, -1) 

                    if debug == 3: # Bei Starlink stopp
                        stream = cv2.imread(fname) 
                        segmask, stream = segment_image.segmentImage (fname, mask_points_values=True, show_bboxes=True)
                        cv2.imshow("Output", stream)
                        cv2.imwrite("mit-starlink.png", stream)
                        cv2.waitKey(0)
                        stream = cv2.imread(fname)
                        cv2.imshow("Output", stream)
                        cv2.imwrite("starlink-orig.png", stream)
                        cv2.waitKey(0)       
            
################ Rest ausserhalb der 20 Sekunden beschriften
                if (uy < 200) or ( uy >= 396):  #196
                    fontScale = 0.6
                    fsize = '--------Flaeche:' + fsize + ' Dopplersh.:' + ds
                  
                ux, uy = org
                uy += 8
                cv2.putText(output, fsize, (ux, uy), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
                fontScale = 0.6
      
    #### Auswertebereich einzeichnen. 196 (200 bis 396) entspricht 20 Sekunden in meinen Plots.
    #### Ausser bei der Dopplershift ist dies der einzige Parameter. Den Wert kann man im Einzelschrittmodus ablesen.
    Ax1 = 300
    Ay1 = 200
    Bx1 = 1350
    By1 = 200
    cv2.line(output, (Ax1, Ay1),(Bx1, By1), light_BLUE, 1)
    Ax2 = 100
    Ay2 = 200 + 196
    Bx2 = 1150
    By2 = 200 + 196

    cv2.line(output, (Ax2, Ay2),(Bx2, By2), light_BLUE, 1)
    print ('>>>>>>>>>>>>  Meteorechos (green) ', globalcount) 
    print ('>>>>>>>>>> Artifical Stars (blue) ', Art_count) 
    print ('>>>>>>>>>>>>>>>>> Backgound (red) ', BG_count) 
    print ('>>>>>>>>>>>>>>>>>>>>UFOs (yellow) ', Err_count)
    if debug == 1:
        cv2.imwrite("test-final.png", output)
        cv2.imshow("Output", output)
        cv2.waitKey(0)
        stream = cv2.imread(fname)
        cv2.imshow("Output", stream)
        cv2.imwrite("test-input.png", stream)
        cv2.waitKey(0) #################

cv2.line(bg,(1,1),(1,500),(WHITE),2)
cv2.line(bg,(1,499),(1900,499), WHITE,2)    # Skala

for grj in range (1,5):
    bg = cv2.line(bg,(0, grj * 100),(15, grj * 100), WHITE,2)   # Y- Ticks 
off = 4
cv2.putText(bg, '1', (5, 500-off), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg, '10', (5, 400-off), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg, '100', (5, 300-off), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg, '1000', (5, 200-off), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg, '10000', (5, 100-off), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg, '100000', (5, 20), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg, 'Size/Pixel', (15, 55), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg,'Time / UTC', (580, 543), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg,'WiSi 2023', (1350,543), font, 0.5, RED, fthickness, cv2.LINE_AA)

cv2.imshow('    ' + day +'. ' + Monat + Aufnahmejahr +' Logarithmus der Flaechen der Echos,' + sname, bg)


with open('datum.txt', 'w') as f:

    for out_count in range (0, 240):                      # 240 für 6 Minuten, 480 für 3 Minuten usw
        susi_i = ("{:8.0f}".format(out_count//(10)))      # 20 = 3 Minuten, 10 = 6 <Minuten
        susi_3min = ("{:8.0f}".format(round(summe_3min[out_count]/1)))
        if out_count > 0: f.write('  ' + susi_i + susi_3min + '   \n')
        if out_count == 0: f.write('  ' + susi_i + susi_3min + '   Aufnahme ' + day + '. '+ Monat + ' 2023' + sname + '\n')
    f.write('\r\n')

    for out_count in range (0, 240):                 
        susi_i = ("{:8.0f}".format(out_count//(10))) 
        susi_3min = ("{:8.0f}".format(round(fsumme_3min[out_count]/1)))
        if out_count > 0: f.write('  ' + susi_i + susi_3min + '   \n')
        if out_count == 0: f.write('  ' + susi_i + susi_3min + '   Aufnahme ' + day + '. '+ Monat + ' 2023' + sname + '\n')
    f.write('\r\n')

isscore = score_100_99 + score_99_98 +score_98_97 + score_97_96 + score_96_95 + score_95_94 + score_94_93 + score_93_90 + score_90_80 + score_80_70
sscore =  score_100_99 + score_99_98 +score_98_97 + score_97_96 + score_96_95 + score_95_94 + score_94_93 + score_93_90 + score_90_80 + score_80_70 + score_70_00

print()
print ('  Score Histogramm der Meteorechos')
print ('  100 % - 99 %  ', score_100_99)
print ('   99 % - 98 %  ', score_99_98)
print ('   98 % - 97 %  ', score_98_97)
print ('   97 % - 96 %  ', score_97_96)
print ('   96 % - 95 %  ', score_96_95)
print ('   95 % - 94 %  ', score_95_94)
print ('   94 % - 93 %  ', score_94_93)
print ('   93 % - 90 %  ', score_93_90)
print ('   90 % - 80 %  ', score_90_80)
print ('   80 % - 70 %  ', score_80_70)
print ('------------------------')
print ('   70 % Summe:   ', isscore)
print ('   kleiner ', Baseline, ':', kleiner_Baseline)
print()
print ('   70 % - 00 %  ', score_70_00)
print ('------------------------')
print ('   100 % Summe:  ', sscore)
print ('   kleiner ', Baseline, ':', kleiner_Baseline_alle)
print ()
print ('   Dauer der Analyse: ')
print ('   Start:',startzeit)
now = datetime.datetime.now()
print ('   Ende: ', now)
print ()
cv2.imwrite("bg.png", bg)

sugesamt = isscore

fl_max = 0
fl_max_i = 0
fl_sum = 0
print (' Histogramm Flaechen ')
for ihis in range (1,25):
    fl_sum = fl_sum + summe_fl[ihis]
    if fl_max < summe_fl[ihis]:
        fl_max = summe_fl[ihis]
        fl_max_i = ihis       
    print (summe_fl[ihis], end = ' |')
print ( '', end = "\r\n")

anz_max = 0
anz_max_i = 0
print (' Histogramm Anzahl ')
for ihis in range (1,25):
    if anz_max < summe_anz[ihis]:
        anz_max = summe_anz[ihis]
        anz_max_i = ihis
    print (summe_anz[ihis], end = ' |')
print ( '', end = "\r\n")


fontScale1 = 0.4
for ihis in range (1,25):
    cv2.rectangle(histogramm, (ihis*20, 250), ((ihis * 20) +10, 250 - int(summe_fl[ihis]/333.33/4)), RED, -1) 
    cv2.rectangle(histogramm, (ihis*20, 500), ((ihis * 20) +10, 500 - summe_anz[ihis]*3//2), YELLOW, -1)
    org = (int(ihis*19.9), 520)
    cv2.putText(histogramm, str(ihis-1), org, font, fontScale1, WHITE, fthickness, cv2.LINE_AA)
                                      # 250 -75 -75
cv2.line(histogramm,(30, 175),(490, 175), darkOlive, 1)
cv2.line(histogramm,(30, 100),(490, 100), darkOlive, 1)
cv2.putText(histogramm, '100k', (4, 175), font, fontScale1, Olive, fthickness, cv2.LINE_AA)
cv2.putText(histogramm, '200k',(4, 100), font, fontScale1, Olive, fthickness, cv2.LINE_AA)

                                      # 500 -75 -75
cv2.line(histogramm,(20, 425),(490, 425), darkOlive, 1)
cv2.line(histogramm,(20, 350),(490, 350), darkOlive, 1)
cv2.putText(histogramm, '50', (4, 425), font, fontScale1, Olive, fthickness, cv2.LINE_AA)
cv2.putText(histogramm, '100', (4, 350), font, fontScale1, Olive, fthickness, cv2.LINE_AA)

cv2.putText(histogramm, ' Summe Flaechen: '+str(int(fl_sum)), (10, 30), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(histogramm, ' max: '+ str(int(fl_max)) + ' um '+ str(fl_max_i - 1)+ ' h', (10, 50), font, fontScale, WHITE, fthickness, cv2.LINE_AA)

cv2.putText(histogramm, ' Anzahl: '+str(int(sugesamt)), (10, 280), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(histogramm, ' max: '+str(anz_max) + ' um ' + str(anz_max_i - 1) + ' h', (10, 300), font, fontScale, WHITE, fthickness, cv2.LINE_AA)

cv2.imshow('    ' + day +'. ' + Monat +' 2023, Histogramme, Zeit in UTC, ', histogramm)

print ('>>>>>>>>>>>>>>>>>>>>>>>>fertig ')

cv2.waitKey(0)
cv2.destroyAllWindows()


Training:
Code:
#   cd C:\Users\Willi\Desktop\k3

import pixellib
import tensorflow as tf
from pixellib.custom_train import instance_custom_training
print("###################Num GPUs Available: ", len(tf.config.list_physical_devices('GPU')))

train_maskrcnn = instance_custom_training()
train_maskrcnn.modelConfig(network_backbone = "resnet101", num_classes= 3, batch_size = 1)
train_maskrcnn.load_pretrained_model("mask_rcnn_coco.h5")
# Im Ordner drei-Klassen befinden sich die Ordner Train und Test
train_maskrcnn.load_dataset("drei-Klassen")
train_maskrcnn.train_model(num_epochs = 200, augmentation=False,  path_trained_models = "drei-Klassen")
 
Zuletzt bearbeitet:
Guten Tag.
Heute habe ich eine schöne Auswertung vom 13. April für Euch. Am 11. April gab es den Blitzeinschlag und am 12. April gab es einen Noisefloor, der die Interpretation schwacher Signale behindert.

Der Peak um 8 h am 13. April passt gut zu dem hellen Bereich im CMOR Plot.
Es wären demnach:
APS, Dayt. April Piscids, Maximum am 16.4.
NOC, North. Dayt. omega Cetids
Die Genehmigung zum Posten von CMOR-Plots liegt vor.

Der Peak um Mitternacht passt gut zu den Virginiden.

Schön ist auch wieder ein Starlink-Batch um ~20:45 h UT zu sehen.

Der Lila Meteor im Bild 3-Meteore&6Starlink ist noch nicht beschriftet und würde auch nicht ausgewertet. Das muss ich noch ergänzen, siehe auch den Programmcode.

Das große Echo ist von heute.

Einen schönen Tag wünsche ich Euch,

besonders viele Grüße sende ich nach Spanien,

viele Grüße
Wilhelm
 

Anhänge

  • April13.png
    April13.png
    454,9 KB · Aufrufe: 48
  • CMOR-April-13-16h-UTC.jpg
    CMOR-April-13-16h-UTC.jpg
    466,3 KB · Aufrufe: 44
  • 3-Meteore&6Starlink.png
    3-Meteore&6Starlink.png
    1.005 KB · Aufrufe: 50
  • 6-Starlink.png
    6-Starlink.png
    988,6 KB · Aufrufe: 47
  • GRAVES-XYmVV_230414030039.jpg
    GRAVES-XYmVV_230414030039.jpg
    606,2 KB · Aufrufe: 50
  • test-final.png
    test-final.png
    929,8 KB · Aufrufe: 53
Zuletzt bearbeitet:
Hallo Wilhelm,

danke für den Code! Du kannst in Python über pip (oder conda) Entwicklungsumgebungen für Projekte erstellen, dass wirst du dann im GitHub Projekt sehen. Das ist super praktisch für Reproduzierbarkeit und Testen, so kann man neue Bibliotheken bzw. Versionen testen ohne die "Hauptentwicklungsumgebung" zu zerstören.

Beispiel, dein Projekt läuft stabil unter Python 3.7 mit Numpy 1.0. Also erstellst du einen Umgebung (nennen wir sie py37_env) dafür und installierst wie gewohnt alles über pip.

Jetzt kommt aber Python 3.10 und eine neue Numpy Version 1.5 herraus und du würdest gerne updaten, bist aber nicht sicher, ob dein Code noch läuft. Also erstellst du eine zweite Umgebung (nennen wir sie py310_env), installierst alles und kannst ganz sicher alles ausprobieren. Du kannst dann ganz einfach ziwschen den verschiedenen Entwicklungsumgebungen hin und herwechseln.

Bezüglich pip freeze, um dein Projekt schnellstmöglich zu reprodiuztuieren brauche ich die genauen Versionen aller Bibliotheken (siehe Screenshot), also Python, Numpy, OpenCV usw. Das kannst du mir per Screenshot schicken (siehe Beispiel, wobei ich nicht weiß welche IDE du nutzt) oder viel einfacher, automatisch extrahieren lassen (du musst keine Entwicklungsumgebung erstellen, es gibt immer eine base env, diese nutzt du gerade).

Schreib einfach in der cmd wo du normalerweise dein Projekt startest (weiter oben war das glaube ich C:\Users\wilsi):

pip freeze > requirements.txt

(Also einfach genau dort, wo du normalerweise zum Beispiel pip install numpy ausführst).

Dann wird eine Textdatei requirements.txt unter dem aktuellen Pfad erstellt. Diese kannst du mir schicken und ich kann mit einem Klick die gleiche
Entwicklungsumgebung wie bei dir klonen (falls es dich interessiert, dass geht via pip install -r requirements.txt) . Somit werden alle Bibliotheken automatisch installiert und es sollte dann in 1 Minute alles out of the box laufen. Cool, oder?

Wenn du magst, kannst du es probieren, dass würde vieles erleichtern.

Das Modell kannst du bei einem Anbieter hochladen (file.io - Super simple file sharing) oder schick mir eine PN, wenn es privat sein soll. Ich schicke dir dann einen gesicherten Upload Server.

Wenn alles läuft stelle ich auf 3D um, für meinen SDRPlay bekomme ich gerade ein Austauschgerät.

Besten Grüße und vielen Dank!
Stefanie
 

Anhänge

  • pip_freeze_beispiel_cmd.PNG
    pip_freeze_beispiel_cmd.PNG
    2,6 KB · Aufrufe: 43
  • pip_freeze_beispiel.PNG
    pip_freeze_beispiel.PNG
    122,6 KB · Aufrufe: 38
  • env_beispiel.PNG
    env_beispiel.PNG
    19,2 KB · Aufrufe: 39
Das überlasse ich Emil.

Hallo Stefanie,
danke für die Info.
Das Hauptproblem sehe ich in dem veralteten Pixellib. Das müsstet du / Ihr erst zum Laufen bringen. Siehe auch hier.
Ein Modell und den aktuellen Code lade ich hoch. Das kann öffentlich sein. Dazu würde ich dann auch einen Ordner mit Spektrum-Lab Testbildern hochladen, z.B. eine Stunde Daten. Allerdings bastele ich gerade, so dass ich erst wieder eine stabile Version generieren muss. Etwas Doku sollte ich auch noch beifügen.
Im ersten Schritt sollten wir das Paket dann bei dir zum Laufen bringen. Danach kannst du das Programm auf deine Bilder los lassen.
Dann werden wir sehen, ob es sich für Github oder so überhaupt eignet.

Was hältst du davon?
Einen schönen Tag wünsche ich Euch,
viele Grüße
Wilhelm
 
Zuletzt bearbeitet:
Hallo Stefanie,
Super!
So, ich habe dir einen Ordner vorbereitet, aber der Upload bricht immer ab, egal, ob als zip oder normal. Ich versuche es später noch mal.
Es ist mein aktueller Code. Ich habe ihn noch mal angehängt. Du musst nur die Pfade an den Stellen ändern, wo Wilsi steht.
Das Bild im Anhang habe ich auf meinem Gaming PC gemacht, habe es aber auch auf meinem normalen PC auch getestet. Da ist es natürlich sehr langsam.
Am besten startest du einen der Debug-Modi. Man muss immer 2 x Enter drücken, einmal für das KI-Bild und noch einmal, um sich das Original noch mal anschauen zu können.
Ich habe einen Datensatz genommen, der viele Starlinks enthält. Die blauen Striche sind das Starlink-Histogramm. Eine Version mit 4 Klassen ist in Arbeit. Daher sind die Zeilen auskommentiert.
Den Link schicke ich per PM wenn es geklappt hat, da die Daten nach einmaligem Download gelöscht werden.
Bis später,
viele Grüße
Wilhelm

Code:
# (C) WiSi-Testpilot, letzte Anderung: 22.4.2023
# cd C:\Users\Wilsi\Desktop\k3s

import glob
import time
import math as m
import random
import datetime
import numpy as np
import cv2
import pixellib
import tensorflow as tf
from shapely.geometry import Polygon

startzeit = datetime.datetime.now()

print("################### Num GPUs Available: ", len(tf.config.list_physical_devices('GPU')))

from pixellib.instance import custom_segmentation
segment_image = custom_segmentation()

#segment_image.inferConfig(num_classes= 4, class_names= ["BG", "Artifical-Star", "Background", "Meteor", "Traeger"])
#segment_image.load_model("C:/Users/Willi/Desktop/k3/vier-Klassen/mask_rcnn_model.069-0.390041.h5")

segment_image.inferConfig(num_classes= 3, class_names= ["BG", "Artifical-Star", "Background", "Meteor"])
segment_image.load_model("C:/Users/Wilsi/Desktop/k3s/drei-Klassen/mask_rcnn_model.040-0.432872.h5")


#>>>>>>>>>>>>>>>>> hier ein paar Startwerte eingeben
sname =  " mask_rcnn_model.040-0.432872, 3-Klassen: Artifical-Star, Background, Meteor"
debug = 1
#   0: normal, batch
#   1: Stop bei Echo,
#   2: Stop bei Score unter 0.8,
#   3: Stop bei Starlink,
#   4: Stop bei Echo > 10000

Aufnahmejahr = " 2023,"

path = glob.glob("C:/Users/Wilsi/Desktop/k3s/SL-Daten/GRAVES-XYmVV_23040806*.jpg") # normale wildcard-Regeln, hier nur 6 h

#path = glob.glob("C:/Users/Willi/Desktop/April4-21/GRAVES-XYmVV_230421*.jpg")
#path = glob.glob("C:/Users/Willi/Desktop/Juni22-8-10/GRAVES-XY-Vv_220609*.jpg")
#path = glob.glob("C:/Users/Willi/Desktop/2022-Dez13-15/GRAVES-xy_221214*.jpg")
#path = glob.glob("C:/Users/Willi/Desktop/DezXY12-24/GRAVES-XY-Vv_211214*.jpg")
#path = glob.glob("C:/Users/Willi/Desktop/Jan3-6-23/GRAVES-xy_2301040*.jpg")

bg = np.zeros((550, 1900, 3), np.uint8)            # Output Display
summe_3min = np.zeros((481), np.uint32)
fsumme_3min = np.zeros((481), np.single)

histogramm = np.zeros((540, 510, 3), np.uint8)    #Histogramm Display
summe_fl   = np.zeros((26), np.single)
summe_anz  = np.zeros((26), np.uint32)
summe_anz_Starlink  = np.zeros((26), np.uint32)

score_100_99 = 0
score_99_98 = 0
score_98_97 = 0
score_97_96 = 0
score_96_95 = 0
score_95_94 = 0
score_94_93 = 0
score_93_90 = 0
score_90_80 = 0
score_80_70 = 0
score_70_00 = 0

Baseline = 700
kleiner_Baseline = 0
kleiner_Baseline_alle = 0
plot_count = 0
globalcount = 0
Art_count = 0
BG_count = 0
Err_count = 0
noisefloor = 1
fontScale = 0.6
fthickness = 1
font = cv2.FONT_HERSHEY_SIMPLEX

RED = (0, 0, 255)  # b g r
GREEN = (20, 255, 20,)
YELLOW = (0, 255, 255)
BLUE = (255, 0, 0)
Magenta = (147, 20, 255)
DarkOrange = (15, 185, 255)  # Gold
WHITE = (200, 200, 200)
Gray = (100, 100, 100)
light_BLUE = (255, 191, 0)
DarkOrange1 = (0, 140, 255)  # alt
lite_MAGENTA = (255, 0, 255)
Rose = (200, 200, 255)
lRED = (20, 20, 200)  # b g r
OrangeRed = (0, 190, 255)  # b g r fast gelb
darkOlive = (40, 120, 40)
Olive = (150, 255, 150)

for fname in path:                      # Analyse über alle Files im Ordner/Folder
    print(' > ', fname)
    position = fname.find(".jpg")       # Zeit und Datum werden aus dem Filenamen extrahiert
    zeit = fname[position-10:position]
    print ("Jahr Monat Tag St. Min. Sek.", '20' + fname[position-12:position])
    monat= zeit[0:2]
    if monat == '01': Monat = 'Januar'
    if monat == '02': Monat = 'Februar'
    if monat == '03': Monat = 'Maerz'
    if monat == '04': Monat = 'April'
    if monat == '05': Monat = 'Mai'
    if monat == '06': Monat = 'Juni'
    if monat == '07': Monat = 'Juli'
    if monat == '08': Monat = 'August'
    if monat == '09': Monat = 'September'
    if monat == '10': Monat = 'Oktober'
    if monat == '11': Monat = 'November'
    if monat == '12': Monat = 'Dezember'
    day= zeit[2:4]
    ho = zeit[4:6]    # Zeit aus Filenamen extrahieren
    mi = zeit[6:8]
    se = zeit[8:10]
 #  print('Monat: ', monat)
 #  print('Tag: ', day)
 #  print (day + '.', Monat, '2023')
    ctime = (float(ho) * 3600 ) + (float(mi) *60) + float(se)   # X-Position aus Zeit berechnen
 #  print('################# ctime  ', round(ctime), '   ', round(ctime/20), '   ', round(ctime/180))
    xa = round (ctime / 60)
    if (mi == '00') and ((se == '00') or (se == '59') or (se == '01') ):
        bg = cv2.line(bg,(xa,500),(xa, 515), WHITE, 2)      # X ganze Stunden-Ticks
        org = (xa, 530)  # war 535
        bg = cv2.putText(bg, ho, org, font, fontScale, WHITE, fthickness, cv2.LINE_AA)

    if ((mi == '30') or (mi == '15') or (mi == '45')) and ((se == '00') or (se == '59') or (se == '01') ):
        bg = cv2.line(bg,(xa,500),(xa, 510), WHITE, 1)        # X 1/4 Stunden-Ticks

    isClosed = True
    dicke = 3
    radius = 4
    org = (0, 0)
    meteor_was_there = False            # Debug
    klein_meteor_was_there = False
    starlink_was_there = False
    ue10000_was_there = False

    paare         = np.zeros((1000,2), np.int32)

    bg_RED        = np.zeros((1000,2), np.int32)
    bg_GREEN      = np.zeros((1000,2), np.int32)
    bg_YELLOW     = np.zeros((1000,2), np.int32)
    bg_BLUE       = np.zeros((1000,2), np.int32)
    bg_Magenta    = np.zeros((1000,2), np.int32)
    bg_DarkOrange = np.zeros((1000,2), np.int32)
    bg_WHITE      = np.zeros((1000,2), np.int32)
 
    bg_light_BLUE   = np.zeros((1000,2), np.int32)
    bg_DarkOrange1  = np.zeros((1000,2), np.int32)
    bg_lite_MAGENTA = np.zeros((1000,2), np.int32)
    bg_Rose         = np.zeros((1000,2), np.int32)
    bg_lRED         = np.zeros((1000,2), np.int32)
    bg_OrangeRed    = np.zeros((1000,2), np.int32)
    bg_darkOlive    = np.zeros((1000,2), np.int32)
    bg_Olive        = np.zeros((1000,2), np.int32)

    summe_RED = 0
    summe_GREEN = 0
    summe_YELLOW = 0
    summe_BLUE = 0
    summe_Magenta = 0
    summe_DarkOrange = 0
    summe_WHITE = 0

    summe_light_BLUE = 0
    summe_DarkOrange1 = 0  
    summe_lite_MAGENTA = 0
    summe_Rose = 0  
    summe_lRED = 0
    summe_OrangeRed = 0
    summe_darkOlive = 0
    summe_Olive = 0

    anz_RED = 0
    anz_GREEN = 0
    anz_YELLOW = 0
    anz_BLUE = 0
    anz_Magenta = 0
    anz_DarkOrange = 0
    anz_WHITE = 0

    anz_light_BLUE = 0
    anz_DarkOrange1 = 0  
    anz_lite_MAGENTA = 0
    anz_Rose = 0  
    anz_lRED = 0
    anz_OrangeRed = 0
    anz_darkOlive = 0
    anz_Olive = 0

    # Bild wird analysiert
    segmask, output = segment_image.segmentImage (fname, mask_points_values=True, show_bboxes=True)  #, output_image_name="2-testy.jpg")
    print ('    rois')
    a = segmask.get('rois')
    print (a)
    print (len(a))
    print ('    class_ids')
    # Noise Floor auswerten
    if len(a) == 0:
        nfmittelwert = 0.0
        if noisefloor == 1:
            for i_nf in range (300, 401):
                for j_nf in range (200, 301):
                    for k_nf in range (0, 3):
                        nfmittelwert = nfmittelwert + output[i_nf, j_nf, k_nf]
            cv2.circle(bg, (xa, 500 - int(nfmittelwert/5000)), 1 , Magenta, -1)
      #      Debugg Noisefloor
      #      print (nfmittelwert/5000)
      #      cv2.rectangle(output, (300, 200), (400, 300), YELLOW, 2)
      #      cv2.imshow("Bild fuer NF", output)
      #      cv2.waitKey(0)
      #      cv2.destroyAllWindows()

    #b = segmask.get('class_ids')
    b = segmask['class_ids'].astype('int')
    print (b)
    print (len(b))
    test  = np.zeros((100), np.int32)
    for itest in range (0, len(b)):
        test[itest] = b[itest]
        print (test[itest]*10)

    print ('    scores')
    c = segmask.get('scores')
    print (c)
    print (len(c))
    if len(c) > 0:
        print ('----masks')
        if len(b) > 1:  d = segmask.get('masks')
        if len(b) == 1:
            try:
                d = segmask['masks'].astype('int')
                print ('################################## len(b) war 1 ')
            except:
                d = segmask.get('masks')
     #  print('*********')
        print (len(d))
     #  print(d)
        anzahl = 0
        anzahl = len(d)
        print ('Anzahl Objekte  ', anzahl)

####### Konturen werden ausgewertet
        counter = 0
        color = Olive
    #   for i in d: cv2.polylines(output, i, isClosed, light_BLUE, dicke)
        for i in d:
            counter += 1
            print('#############   ', b[counter -1])
            if counter == 1:
                color = RED
                bg_RED  = i
            if counter == 2:
                color = GREEN
                bg_GREEN  = i
            if counter == 3:
                color = YELLOW
                bg_YELLOW  = i
            if counter == 4:
                color = BLUE
                bg_BLUE  = i
            if counter == 5:
                color = Magenta
                bg_Magenta  = i
            if counter == 6:
                color = DarkOrange
                bg_DarkOrange  = i
            if counter == 7:
                color = WHITE
                bg_WHITE  = i    
 
            if counter == 8:
                color =  light_BLUE
                bg_light_BLUE = i
            if counter == 9:
                color =  DarkOrange1
                bg_DarkOrange1 = i
            if counter == 10:
                color = lite_MAGENTA
                bg_lite_MAGENTA = i
            if counter == 11:
                color = Rose
                bg_Rose = i
            if counter == 12:
                color = lRED
                bg_lRED = i
            if counter == 13:
                color = OrangeRed
                bg_OrangeRed = i
            if counter == 14:
                color = darkOlive
                bg_darkOlive = i
            if counter == 15:
                color = Olive
                bg_Olive = i


        print('Anzahl der Bruchstuecke ')
        print(len(bg_RED))
        print(len(bg_GREEN))
        print(len(bg_YELLOW))
        print(len(bg_BLUE))
        print(len(bg_Magenta))
        print(len(bg_DarkOrange))
        print(len(bg_WHITE))
        print(len(bg_light_BLUE))
        # hier fehlt noch 9-15
        print(' >>>>>>>>> 1000 = leer')


        for o in range (1, anzahl +1):
            if o == 1:
                bg_temp = bg_RED
                col_temp = RED
                col_name = 'RED'
            if o == 2:
                bg_temp = bg_GREEN
                col_temp = GREEN
                col_name = 'GREEN'
            if o == 3:
                bg_temp = bg_YELLOW
                col_temp = YELLOW
                col_name = 'YELLOW'
            if o == 4:
                bg_temp = bg_BLUE
                col_temp = BLUE
                col_name = 'BLUE'
            if o == 5:
                bg_temp = bg_Magenta
                col_temp = Magenta
                col_name = 'Magenta'
            if o == 6:
                bg_temp = bg_DarkOrange
                col_temp = DarkOrange
                col_name = 'DarkOrange'
            if o == 7:
                bg_temp = bg_WHITE
                col_temp = WHITE
                col_name = 'WHITE'
########### hier fehlt noch 8-15
          #  if test[o-1] > 1: cv2.fillPoly(output, bg_temp, col_temp)

            laenge = len(bg_temp)
            print ('  Bruchstuecke von: ', col_name, '   ', laenge)
            counter = 0
            summe = 0
            xsumme = 0
            ysumme = 0
            for ii in bg_temp:
                print ('  Anzahl Wertepaare: ', len(ii))
                paare = np.zeros((len(ii),2), np.int32)
                if len(ii) >= 3:
                    counter = 0
                    for jj in ii:
                        paare[counter] = jj
                        counter += 1
                    cv2.fillPoly(output, [paare], col_temp)
                    pgon = Polygon(paare)
                    summe += pgon.area
                    print ('  Flaeche ', col_name, '      ', pgon.area)
                    mitte_x = round(pgon.centroid.x)
                    xsumme += mitte_x
                    mitte_y = round(pgon.centroid.y)
                    ysumme += mitte_y
                    print ('  Zentrum ', col_name, '  X= ', mitte_x, '  Y= ', mitte_y)
                if len(ii) < 3:
                    print (' >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>verworfen  ')
                    laenge -= 1
            if laenge > 1:
                print (' >>>>>> Mittelwert Zentrum: ', col_name, '  Xs= ', round(xsumme / laenge), '  Ys= ', round(ysumme / laenge))
                print (' >>>>>>>> Summe der Fläche: ', summe)
 
   
########### Dopplershift berechnen          
            if laenge > 0:
                org = (round(xsumme / laenge), round(ysumme / laenge))
                Ax = 945       # Projektionslini für die Dopplerschift
                Ay = 609    
                Bx = 350
                By = 28  
                cv2.line(output, (Ax, Ay),(Bx, By), Magenta, 1)
                cv2.putText(output, ('Ax, Ay'), (Ax, Ay), font, fontScale, WHITE, fthickness, cv2.LINE_AA)

                dx = Bx - Ax
                dy = By - Ay
                cqu = dx*dx + dy*dy
                c_geo = m.sqrt(cqu)
         #      print ('  c_geo  ', c_geo)

                ux, uy = org

                dx = Bx - ux
                dy = By - uy
                a1_geo = m.sqrt(dx*dx + dy*dy)
         #      print ('  a1_geo  ',a1_geo)

                dx = Ax - ux
                dy = Ay - uy
                b1_geo = m.sqrt(dx*dx + dy*dy)
         #      print ('  b1_geo  ',b1_geo)
                try:    
                   cos_alpha = (b1_geo * b1_geo + cqu - a1_geo * a1_geo)/(2*b1_geo * c_geo) #Cosinussatz
                except:
                   cos_alpha = 0.7
         #      print ('  cos alpha  ', cos_alpha)
                try:
                    A_arc = m.acos(cos_alpha)
                except:
                    A_arc = 99
                sin_A = m.sin(A_arc)
                cos_A = m.cos(A_arc)
                A_deg = np.rad2deg(A_arc)
         #      print ('  Alpha  ',A_deg)
                hoehe1 = b1_geo * sin_A
         #      print ('  Hoehe: ', hoehe1)
                dopplershift =  round (m.sqrt(a1_geo * a1_geo - hoehe1 * hoehe1))    
                print ('  rel. Dopplershift: ', dopplershift)
############### Ende Dopplershift

                print (' >>>>>>>>>>>>>>>>>>>> Klasse: ', test[o-1])
                cv2.circle(output, org, 6 , WHITE, -1)
                if col_name == 'RED': cv2.circle(output, org, 3 , GREEN, -1)
                if col_name != 'RED': cv2.circle(output, org, 3 , RED, -1)
                fsize = ("{:5.0f}".format(summe))
                ds = ("{:3.0f}".format(dopplershift))

############ Flags fuer debug
                if test[o-1] == 1: starlink_was_there = True
                if test[o-1] == 3: meteor_was_there = True
                if c[o-1] < 0.8: klein_meteor_was_there = True
                if test[o-1] == 3 and summe > 10000: ue10000_was_there = True

############ Echos im Bereich 200 bis 396 loggen. 196 (200 bis 396) entspricht 20 Sekunden in meinen Plots.
############ Ausser bei der Dopplershift ist dies der einzige Parameter. Den Wert kann man im Einzelschrittmodus ablesen.
 
                if (uy >= 200) and ( uy < 396) and (test[o-1] == 3) and (dopplershift > 300) and (dopplershift < 700) and (summe < 100000):
                    fontScale = 0.6
                    fsize = '++++++Flaeche:' + fsize + ' Dopplersh.:' + ds
                    print (' Score in Window ', c[o-1])

                    if (c[o-1] <= 1.00) and (c[o-1] > 0.99): score_100_99 += 1
                    if (c[o-1] <= 0.99) and (c[o-1] > 0.98): score_99_98 += 1
                    if (c[o-1] <= 0.98) and (c[o-1] > 0.97): score_98_97 += 1
                    if (c[o-1] <= 0.97) and (c[o-1] > 0.96): score_97_96 += 1
                    if (c[o-1] <= 0.96) and (c[o-1] > 0.95): score_96_95 += 1
                    if (c[o-1] <= 0.95) and (c[o-1] > 0.94): score_95_94 += 1
                    if (c[o-1] <= 0.94) and (c[o-1] > 0.93): score_94_93 += 1
                    if (c[o-1] <= 0.93) and (c[o-1] > 0.90): score_93_90 += 1                
                    if (c[o-1] <= 0.90) and (c[o-1] > 0.80): score_90_80 += 1
                    if (c[o-1] <= 0.80) and (c[o-1] > 0.72): score_80_70 += 1  
                    if (c[o-1] <= 0.72) and (c[o-1] > 0.00): score_70_00 += 1  
                   
                    offset_summe = summe - Baseline
                    if offset_summe <= 0:
                        offset_summe = 1
                        kleiner_Baseline_alle +=1

                    if (c[o-1] >= 0.72):  # nur hier loggen
                        y_t_color = GREEN              
                        if offset_summe == 1: kleiner_Baseline += 1
                        fl = int(495 -100 * m.log10(offset_summe))
                        globalcount += 1      
                        bg = cv2.circle(bg, (xa, fl), dicke , y_t_color, -1)
                        plot_count = m.trunc(ctime / 360)   # 180 360
                        summe_3min[plot_count] += 1
                        fsumme_3min[plot_count] = fsumme_3min[plot_count] + summe  

                        summe_anz[int(ho)+1]  +=1
                        summe_fl[int(ho)+1] = summe_fl[int(ho)+1] + summe                      
                       
################ Echos liegen zu nahe am Rand
                if (uy >= 200) and ( uy < 396) and (test[o-1] == 3) and ((dopplershift <= 300) or (dopplershift >= 700)):
                    fontScale = 0.6
                    fsize = '-x-W-x--Flaeche:' + fsize + ' Dopplersh.:' + ds
                    y_t_color = YELLOW
                    Err_count += 1
                    offset_summe = summe - Baseline
                    if offset_summe <= 0: offset_summe = 1
                    fl = int(495 -100 * m.log10(summe))
                    bg = cv2.circle(bg, (xa, fl), dicke , y_t_color, -1)            
                   
################ Background innerhalb der 20 Sekunden loggen
                if (uy >= 200) and ( uy < 396) and (test[o-1] == 2) and (dopplershift >= 20): # Rand weg
                    fontScale = 0.6
                    fsize = '----R---Flaeche:' + fsize + ' Dopplersh.:' + ds
                    y_t_color = RED
                    BG_count += 1
                    offset_summe = summe - Baseline
                    if offset_summe <= 0: offset_summe = 1
                    fl = int(495 -100 * m.log10(offset_summe))
                    bg = cv2.circle(bg, (xa, fl), 2 , y_t_color, -1)    # 2 = dicke        
                 
################ Starlinks innerhalb der 20 Sekunden loggen
                if (uy >= 200) and ( uy < 396) and (test[o-1] == 1) and (c[o-1] >= 0.0):
                    fontScale = 0.6
                    fsize = '----B----Flaeche:' + fsize + ' Dopplersh.:' + ds
                    y_t_color = BLUE
                    Art_count += 1
                    offset_summe = summe - Baseline
                    if offset_summe <= 0: offset_summe = 1
                    fl = int(495 -100 * m.log10(offset_summe))
                    bg = cv2.circle(bg, (xa, fl), dicke , y_t_color, -1)  
                    summe_anz_Starlink[int(ho)+1]  +=1
             
################ Rest ausserhalb der 20 Sekunden beschriften
                if (uy < 200) or ( uy >= 396):  #196
                    fontScale = 0.6
                    fsize = '--------Flaeche:' + fsize + ' Dopplersh.:' + ds

################ Traeger Klasse 4 (Traeger) ist noch in Arbeit
                if (uy >= 200) and ( uy < 396) and (test[o-1] == 4):
                    fontScale = 0.6
                    fsize = '----Tr----Flaeche:' + fsize + ' Dopplersh.:' + ds
                    cv2.line(bg, (xa, 450),(xa, 440), DarkOrange, 1)
                 
                ux, uy = org
                uy += 8
                cv2.putText(output, fsize, (ux, uy), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
                fontScale = 0.6
       
    #### Auswertebereich einzeichnen. 196 (200 bis 396) entspricht 20 Sekunden in meinen Plots.
    #### Ausser bei der Dopplershift ist dies der einzige Parameter. Den Wert kann man im Einzelschrittmodus ablesen.
    Ax1 = 300
    Ay1 = 200
    Bx1 = 1350
    By1 = 200
    cv2.line(output, (Ax1, Ay1),(Bx1, By1), light_BLUE, 1)
    Ax2 = 100
    Ay2 = 200 + 196
    Bx2 = 1150
    By2 = 200 + 196
    cv2.line(output, (Ax2, Ay2),(Bx2, By2), light_BLUE, 1)

    print ()
    print ('>>>>>>>>>>>>  Meteorechos (green) ', globalcount)  
    print ('>>>>>>>>>> Artifical Stars (blue) ', Art_count)  
    print ('>>>>>>>>>>>>>>>>> Backgound (red) ', BG_count)  
    print ('>>>>>>>>>>>>>>>>>>>>UFOs (yellow) ', Err_count)

           
    if (debug == 1 and meteor_was_there == True) or ( debug == 2 and klein_meteor_was_there == True) or \
    (debug == 3 and starlink_was_there == True)  or ( debug == 4 and ue10000_was_there == True):
        cv2.imwrite("output.png", output)
        cv2.imshow("Output", output)
        cv2.waitKey(0)
        stream = cv2.imread(fname)
        cv2.imshow("Output", stream)
        cv2.imwrite("input.png", stream)
        cv2.waitKey(0) #################

cv2.line(bg,(1,1),(1,500),(WHITE),2)
cv2.line(bg,(1,499),(1900,499), WHITE,2)    # Skala

for grj in range (1,5):
    bg = cv2.line(bg,(0, grj * 100),(15, grj * 100), WHITE,2)   # Y- Ticks  
off = 4
cv2.putText(bg, '1', (5, 500-off), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg, '10', (5, 400-off), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg, '100', (5, 300-off), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg, '1000', (5, 200-off), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg, '10000', (5, 100-off), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg, '100000', (5, 20), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg, 'Size/Pixel', (15, 55), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg,'Time / UTC', (580, 543), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg,'WiSi 2023', (1350,543), font, 0.5, RED, fthickness, cv2.LINE_AA)

cv2.imshow('    ' + day +'. ' + Monat + Aufnahmejahr +' Logarithmus der Flaechen der Echos,' + sname, bg)
cv2.imwrite("bg.png", bg)


isscore = score_100_99 + score_99_98 +score_98_97 + score_97_96 + score_96_95 + score_95_94 + score_94_93 + score_93_90 + score_90_80 + score_80_70
sscore =  score_100_99 + score_99_98 +score_98_97 + score_97_96 + score_96_95 + score_95_94 + score_94_93 + score_93_90 + score_90_80 + score_80_70 + score_70_00

print()
print ('  Score Histogramm der Meteorechos')
print ('  100 % - 99 %  ', score_100_99)
print ('   99 % - 98 %  ', score_99_98)
print ('   98 % - 97 %  ', score_98_97)
print ('   97 % - 96 %  ', score_97_96)
print ('   96 % - 95 %  ', score_96_95)
print ('   95 % - 94 %  ', score_95_94)
print ('   94 % - 93 %  ', score_94_93)
print ('   93 % - 90 %  ', score_93_90)
print ('   90 % - 80 %  ', score_90_80)
print ('   80 % - 70 %  ', score_80_70)
print ('------------------------')
print ('   70 % Summe:   ', isscore)
print ('   kleiner ', Baseline, ':', kleiner_Baseline)
print()
print ('   70 % - 00 %  ', score_70_00)
print ('------------------------')
print ('   100 % Summe:  ', sscore)
print ('   kleiner ', Baseline, ':', kleiner_Baseline_alle)
print ()
print ('   Dauer der Analyse: ')
print ('   Start:',startzeit)
now = datetime.datetime.now()
print ('   Ende: ', now)
print ()


sugesamt = isscore

fl_max = 0
fl_max_i = 0
fl_sum = 0
print (' Histogramm Flaechen ')
for ihis in range (1,25):
    fl_sum = fl_sum + summe_fl[ihis]
    if fl_max < summe_fl[ihis]:
        fl_max = summe_fl[ihis]
        fl_max_i = ihis        
    print (summe_fl[ihis], end = ' |')
print ( '', end = "\r\n")

anz_max = 0
anz_max_i = 0
print (' Histogramm Anzahl ')
for ihis in range (1,25):
    if anz_max < summe_anz[ihis]:
        anz_max = summe_anz[ihis]
        anz_max_i = ihis
    print (summe_anz[ihis], end = ' |')
print ( '', end = "\r\n")


fontScale1 = 0.4
for ihis in range (1,25):
    cv2.rectangle(histogramm, (ihis*20, 250), ((ihis * 20) +10, 250 - int(summe_fl[ihis]/333.33/4)), RED, -1)  
    cv2.rectangle(histogramm, (ihis*20, 500), ((ihis * 20) +10, 500 - summe_anz[ihis]*3//2), YELLOW, -1)
    cv2.rectangle(histogramm, (ihis*20 +4, 500), ((ihis * 20) + 6, 500 - summe_anz_Starlink[ihis]*30//2), light_BLUE, -1)    # Starlink
    org = (int(ihis*19.9), 520)
    cv2.putText(histogramm, str(ihis-1), org, font, fontScale1, WHITE, fthickness, cv2.LINE_AA)
                                      # 250 -75 -75
cv2.line(histogramm,(30, 175),(490, 175), darkOlive, 1)
cv2.line(histogramm,(30, 100),(490, 100), darkOlive, 1)
cv2.putText(histogramm, '100k', (4, 175), font, fontScale1, Olive, fthickness, cv2.LINE_AA)
cv2.putText(histogramm, '200k',(4, 100), font, fontScale1, Olive, fthickness, cv2.LINE_AA)

                                      # 500 -75 -75
cv2.line(histogramm,(20, 425),(490, 425), darkOlive, 1)
cv2.line(histogramm,(20, 350),(490, 350), darkOlive, 1)
cv2.putText(histogramm, '50', (4, 425), font, fontScale1, Olive, fthickness, cv2.LINE_AA)
cv2.putText(histogramm, '5', (4, 438), font, fontScale1, light_BLUE, fthickness, cv2.LINE_AA)
cv2.putText(histogramm, '100', (4, 350), font, fontScale1, Olive, fthickness, cv2.LINE_AA)
cv2.putText(histogramm, '10', (4, 363), font, fontScale1, light_BLUE, fthickness, cv2.LINE_AA)

cv2.putText(histogramm, ' Summe Flaechen: '+str(int(fl_sum)), (10, 30), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(histogramm, ' max: '+ str(int(fl_max)) + ' um '+ str(fl_max_i - 1)+ ' h', (10, 50), font, fontScale, WHITE, fthickness, cv2.LINE_AA)

cv2.putText(histogramm, ' Anzahl: '+str(int(sugesamt)), (10, 280), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(histogramm, ' max: '+str(anz_max) + ' um ' + str(anz_max_i - 1) + ' h', (10, 300), font, fontScale, WHITE, fthickness, cv2.LINE_AA)

cv2.imshow('    ' + day +'. ' + Monat +' 2023, Histogramme, Zeit in UTC, Blau = Starlink', histogramm)



with open('datum.txt', 'w') as f:

    for out_count in range (0, 240):                      # 240 für 6 Minuten, 480 für 3 Minuten usw
        susi_i = ("{:8.0f}".format(out_count//(10)))      # 20 = 3 Minuten, 10 = 6 <Minuten
        susi_3min = ("{:8.0f}".format(round(summe_3min[out_count]/1)))
        if out_count > 0: f.write('  ' + susi_i + susi_3min + '   \n')
        if out_count == 0: f.write('  ' + susi_i + susi_3min + '   Aufnahme ' + day + '. '+ Monat + ' 2023' + sname + '\n')
    f.write('\r\n')

    for out_count in range (0, 240):                  
        susi_i = ("{:8.0f}".format(out_count//(10)))  
        susi_3min = ("{:8.0f}".format(round(fsumme_3min[out_count]/1)))
        if out_count > 0: f.write('  ' + susi_i + susi_3min + '   \n')
        if out_count == 0: f.write('  ' + susi_i + susi_3min + '   Aufnahme ' + day + '. '+ Monat + ' 2023' + sname + '\n')
    f.write('\r\n')


print ('>>>>>>>>>>>>>>>>>>>>>>>>fertig ')
cv2.waitKey(0)
cv2.destroyAllWindows()
 

Anhänge

  • Test-Stefanie.png
    Test-Stefanie.png
    213,5 KB · Aufrufe: 47
Zuletzt bearbeitet:
Guten Tag.
Ein kleines Update:
Im Moment läuft es nicht optimal. Gestern hatte ich eine Störung, die selten, aber massiv auftritt und die Langzeitaufnahme kaputt macht. Mit der alten Auswertesoftware konnte ich das ausgleichen, möchte die aber für die KI-Version nicht direkt übernehmen.
Ferner gibt es gelegentlich eine Störung ganz nahe am GRAVES Träger, die kleine Meteor-ähnliche Signale vortäuscht. Eine neue Klasse sollte die Störung beseitigen. Das funktioniert auch, kostet aber wieder kleine Signale.
Unten habe ich den 23 April, das Maximum der Lyriden, von 0 h bis 9 h UT geplottet. Dargestellt sind sind 2022, 2023, das 3-Klassen-Modell und das 4-Klassen-Modell, das die Störungen beseitigen soll.

Man erkennt, dass die Lyriden möglicherweise auch eine Kerbe haben. Kerben sind bei den südlichen Strömen besser ausgeprägt und treten dann auf, wenn der Azimut 180° beträgt. Bei den starken Strömen gibt es dann noch einen In-Line-Peak. Der Radiant der Lyriden hatte seine höchste Elevation von 79° um 3:45 h UT. Da betrug der Azimut 180°. Die Werte habe ich mit Stellarium Web bestimmt. Als Radiant diente der Stern HD 166229. Die Daten stimmen allerdings nicht gut mit der beobachteten Kerbe überein.
Noch etwas Hardware: Ich habe mir einen Spannungswandler besorgt, der 12 V in 19 V für den PC umwandeln kann. Zum Glück produziert das Teil keine Störungen auf 2 m. Nun bestelle ich mir noch einen 12 V 50 Ah LiFePO4 Akku. Bei warmen Wetter kann ich dann mal einen Feldversuch machen.
Einen schönen Tag wünsche ich Euch,
viele Grüße,
Wilhelm
 

Anhänge

  • Spannungswandler.jpg
    Spannungswandler.jpg
    2,5 MB · Aufrufe: 54
  • April23-2022&23.png
    April23-2022&23.png
    114,7 KB · Aufrufe: 47
Hallo Stefanie,
hier ist ein Beispiel. In meinen Daten findest du sie unter W-Traeger…
W wegen der alphabetischen Reihenfolge: Artifical-Star, Background, C bis V für Meteore und W = Träger.
Ich denke, dass mehr labeln helfen wird.
Große Echos, wie es sie bei den Lyriden gab, sind auch nur wenige drin.

Aber zuerst schreibe ich ein Programm, das mir die verschiedenen Größen als Kurven plottet, ähnlich wie in der alten Software. Dann erkennt man Kerben und solche Artefakte besser. Der nächste Strom mit Kerbe sind die Eta-Aquariiden am 6. Mai.
Einen schönen Abend wünsche ich,
viele Grüße
Wilhelm
 

Anhänge

  • input.png
    input.png
    974,7 KB · Aufrufe: 45
  • output.png
    output.png
    947,1 KB · Aufrufe: 49
Zuletzt bearbeitet:
Guten Tag.
Kleines Update: Hier möchte ich einen ersten Versuch mit dem neuen Plotprogramm zeigen.
Die zeitliche Auflösung lässt sich von 1 h bis 3 Minuten einstellen. Hier ist sie eine halbe Stunde.
Die grüne Kurve zeigt die Summe aller Meteore. Unten die orange-farbige Kurve zeigt die Größen. Die rote Kurve zeigt die Echos mit einem Score besser gleich 98 %. Die anderen bunten Kurven zeigen die Histogramme der unterschiedlichen Größen.
Der Tagesverlauf zeigt zwei Maxima, die durch einen Einbruch um 4 bis 5 h UT entstehen. Die Spitzen der Maxima zeigen am 5. Mai je eine Delle. Ursache für diesen Verlauf sind zwei Radianten(felder), die sich zum normalen Tagesgang addieren. Vormittags sind es die Eta-Aquariiden und um Mitternacht herum ist es das Radiantenfeld im Süden auf dem CMOR-Screenshot von heute. Vielleicht sind die Alpha-Scorpiiden dabei. Es sind aber auch Mondechos enthalten.
Die Genehmigung zum Posten von CMOR Screenshots liegt vor.
Ein schönes Wochenende wünsche ich Euch,
viele Grüße
Wilhelm
 

Anhänge

  • Erster-Plot-Mai4&5.png
    Erster-Plot-Mai4&5.png
    139 KB · Aufrufe: 40
  • Cmor-Mai-6.png
    Cmor-Mai-6.png
    659,1 KB · Aufrufe: 36
Nachtrag:
Nach den Eta-Aquariiden kommen noch die:

NOC, North. Dayt. omega Cetids,
SMA, South. Dayt. May Arietids,
OCE, South. Dayt. omega Cetids,

siehe Screenshot von gestern, dem 5. Mai.
Vielleicht stammt daher der Peak um 9 h. Das lässt sich bestimmt besser untersuchen, wenn die Ströme abgeebbt sind.
 

Anhänge

  • Cmor-Mai-5-b.png
    Cmor-Mai-5-b.png
    681,8 KB · Aufrufe: 43
Guten Tag.
GRAVES hat gestern, am 11. Mai eine etwa 4 h lange Sendepause eingelegt. Da der Noise-Floor durchgängig vorhanden ist, kann es kein Fehler meiner Anlage gewesen sein.

Die Bilder zeigen einen Vergleich zwischen der alten, konventionellen Auswertemethode und der Machine-Learning-Methode.
Die alte Methode erkennt 939 Echos, bei der neuen Methode sind es 1433 Echos. Am Tag davor ohne Pause waren es 1800.
Das 4-Klassen Modell, das eine bestimmte Störung beseitigen sollte, habe ich verworfen. Stattdessen wird die Störung nun anhand einer typischen Dopplershift und der Größe der Echos rausgeworfen. Das ist an den rose Punkten z.B. um ~1 h, 22 h und 23 h zu erkennen.

Einen sonnigen Tag wünsche ich Euch und
viele Grüße
Wilhelm
 

Anhänge

  • konventionell.png
    konventionell.png
    450,5 KB · Aufrufe: 40
  • Mai11n.png
    Mai11n.png
    337,1 KB · Aufrufe: 39
  • Mai10n.png
    Mai10n.png
    346 KB · Aufrufe: 35
Hallo Wilhelm,

Ich hatte zwischen 8 und 10.45 Uhr auch keine Empfangen, also wirst du mit deiner Vermutung recht haben. Mir fehlt immer noch etwas Zeit aber Stück für Stück bau ich weiter und nehme fleißig auf ;)

Ich hatte kurz deinen Code überflogen aber konnte auf dem ersten Blick nichts finden. Wilhelm, wie sortierst du die doppelt aufgenommen Meteore aus?

Beste Grüße
Stefanie
 
Zuletzt bearbeitet:
Hallo Stefanie,
meine Plots sind ja 60+ Sekunden lang und ich nehme alle 20 s einen Plot auf. Daher sind manche Echos 3 x geloggt. Dadurch werden auch große Echos komplett erfasst und es ist meistens ein Echo in der Bildmitte.
Ausgezählt wird aber nur der 20 s Bereich zwischen den blauen Linien. Daher steht am Echo der Text +++++Flaeche. Bei denen außerhalb steht ----Flaeche.
Ich habe noch mal den aktuellen Code angehängt.
Einen schönen Tag und viele Grüße
Wilhelm

Code:
# (C) WiSi-Testpilot, letzte Anderung: 11.5.2023
# cd C:\Users\Wilsi\Desktop\k3

import glob
import time
import math as m
import random
import datetime
import numpy as np
import cv2
import pixellib
import tensorflow as tf
from shapely.geometry import Polygon

startzeit = datetime.datetime.now()

print("#### Num GPUs Available: ", len(tf.config.list_physical_devices('GPU')))

from pixellib.instance import custom_segmentation
segment_image = custom_segmentation()

segment_image.inferConfig(num_classes= 3, class_names= ["BG", "Artifical-Star", "Background", "Meteor"])
segment_image.load_model("C:/Users/Wilsi/Desktop/k3/drei-Klassen/mask_rcnn_model.040-0.432872.h5")
sname =  " mask_rcnn_model.040-0.432872, Filter 550/1000 "

debug = 1
#   0: normal, batch
#   1: Stop bei Echo,
#   2: Stop bei Score unter 0.8,
#   3: Stop bei Starlink,
#   4: Stop bei Echo > 10000
#   5: Stop bei jedem Plot, also auch bei leeren Bilden
#   6: Stop bei dopplershift > 550 and summe < 1000    # 550 und 1000 sind Parameter

Aufnahmejahr = " 2023,"

path = glob.glob("C:/Users/Wilsi/Desktop/mai11/GRAVES-xymVV_230512*.jpg") # normale wildcard-Regeln

#path = glob.glob("C:/Users/Willi/Desktop/Met-Mai22XY-1-31/GRAVES-XY-Vv_220505*.jpg")
#path = glob.glob("C:/Users/Wilsi/Desktop/Juni22-8-10/GRAVES-XY-Vv_220609102*.jpg")
#path = glob.glob("C:/Users/Willi/Desktop/2022-Dez13-15/GRAVES-xy_221214*.jpg")
#path = glob.glob("C:/Users/Willi/Desktop/DezXY12-24/GRAVES-XY-Vv_211214*.jpg")
#path = glob.glob("C:/Users/Willi/Desktop/Jan3-6-23/GRAVES-xy_230104*.jpg")

bg = np.zeros((550, 1900, 3), np.uint8)            # Output Display

summe_3min  = np.zeros((481), np.uint32)
fsumme_3min = np.zeros((481), np.single)
su1 = np.zeros((481), np.uint32)
su2 = np.zeros((481), np.uint32)
su3 = np.zeros((481), np.uint32)
su4 = np.zeros((481), np.uint32)
su5 = np.zeros((481), np.uint32)
su6 = np.zeros((481), np.uint32)

histogramm = np.zeros((540, 510, 3), np.uint8)    #Histogramm Display
summe_fl   = np.zeros((26), np.single)
summe_anz  = np.zeros((26), np.uint32)
summe_anz_Starlink  = np.zeros((26), np.uint32)

score_100_99 = 0
score_99_98 = 0
score_98_97 = 0
score_97_96 = 0
score_96_95 = 0
score_95_94 = 0
score_94_93 = 0
score_93_90 = 0
score_90_80 = 0
score_80_70 = 0
score_70_00 = 0

Baseline = 700
kleiner_Baseline = 0
kleiner_Baseline_alle = 0
plot_count = 0
globalcount = 0
Art_count = 0
BG_count = 0
Err_count = 0
noisefloor = 1
fontScale = 0.6
fthickness = 1
font = cv2.FONT_HERSHEY_SIMPLEX

RED = (0, 0, 255)  # b g r
GREEN = (20, 255, 20,)
YELLOW = (0, 255, 255)
BLUE = (255, 0, 0)
Magenta = (147, 20, 255)
DarkOrange = (15, 185, 255)  # Gold
WHITE = (200, 200, 200)
Gray = (100, 100, 100)
light_BLUE = (255, 191, 0)
DarkOrange1 = (0, 140, 255)  # alt
lite_MAGENTA = (255, 0, 255)
Rose = (200, 200, 255)
lRED = (20, 20, 200)  # b g r
OrangeRed = (0, 190, 255)  # b g r fast gelb
darkOlive = (40, 120, 40)
Olive = (150, 255, 150)

for fname in path:                      # Analyse über alle Files im Ordner/Folder
    print(' > ', fname)
    position = fname.find(".jpg")       # Zeit und Datum werden aus dem Filenamen extrahiert
    zeit = fname[position-10:position]
    print ("Jahr Monat Tag St. Min. Sek.", '20' + fname[position-12:position])
    monat= zeit[0:2]
    if monat == '01': Monat = 'Januar'
    if monat == '02': Monat = 'Februar'
    if monat == '03': Monat = 'Maerz'
    if monat == '04': Monat = 'April'
    if monat == '05': Monat = 'Mai'
    if monat == '06': Monat = 'Juni'
    if monat == '07': Monat = 'Juli'
    if monat == '08': Monat = 'August'
    if monat == '09': Monat = 'September'
    if monat == '10': Monat = 'Oktober'
    if monat == '11': Monat = 'November'
    if monat == '12': Monat = 'Dezember'
    day= zeit[2:4]
    ho = zeit[4:6]    # Zeit aus Filenamen extrahieren
    mi = zeit[6:8]
    se = zeit[8:10]
 #  print('Monat: ', monat)
 #  print('Tag: ', day)
 #  print (day + '.', Monat, '2023')
    ctime = (float(ho) * 3600 ) + (float(mi) *60) + float(se)   # X-Position aus Zeit berechnen
 #   print('################# ctime  ', round(ctime), '   ', round(ctime/20), '   ', round(ctime/180))
    xa = round (ctime / 60)
    if (mi == '00') and ((se == '00') or (se == '59') or (se == '01') ):
        bg = cv2.line(bg,(xa,500),(xa, 515), WHITE, 2)      # X ganze Stunden-Ticks
        org = (xa, 530)  # war 535
        bg = cv2.putText(bg, ho, org, font, fontScale, WHITE, fthickness, cv2.LINE_AA)

    if ((mi == '30') or (mi == '15') or (mi == '45')) and ((se == '00') or (se == '59') or (se == '01') ):
        bg = cv2.line(bg,(xa,500),(xa, 510), WHITE, 1)        # X 1/4 Stunden-Ticks

    isClosed = True
    dicke = 3
    radius = 4
    org = (0, 0)
    meteor_was_there = False            # Debug
    klein_meteor_was_there = False
    starlink_was_there = False
    ue10000_was_there = False
    traeger_was_there = False

    paare         = np.zeros((1000,2), np.int32)

    bg_RED        = np.zeros((1000,2), np.int32)
    bg_GREEN      = np.zeros((1000,2), np.int32)
    bg_YELLOW     = np.zeros((1000,2), np.int32)
    bg_BLUE       = np.zeros((1000,2), np.int32)
    bg_Magenta    = np.zeros((1000,2), np.int32)
    bg_DarkOrange = np.zeros((1000,2), np.int32)
    bg_WHITE      = np.zeros((1000,2), np.int32)
 
    bg_light_BLUE   = np.zeros((1000,2), np.int32)
    bg_DarkOrange1  = np.zeros((1000,2), np.int32)
    bg_lite_MAGENTA = np.zeros((1000,2), np.int32)
    bg_Rose         = np.zeros((1000,2), np.int32)
    bg_lRED         = np.zeros((1000,2), np.int32)
    bg_OrangeRed    = np.zeros((1000,2), np.int32)
    bg_darkOlive    = np.zeros((1000,2), np.int32)
    bg_Olive        = np.zeros((1000,2), np.int32)

    summe_RED = 0
    summe_GREEN = 0
    summe_YELLOW = 0
    summe_BLUE = 0
    summe_Magenta = 0
    summe_DarkOrange = 0
    summe_WHITE = 0

    summe_light_BLUE = 0
    summe_DarkOrange1 = 0  
    summe_lite_MAGENTA = 0
    summe_Rose = 0  
    summe_lRED = 0
    summe_OrangeRed = 0
    summe_darkOlive = 0
    summe_Olive = 0

    anz_RED = 0
    anz_GREEN = 0
    anz_YELLOW = 0
    anz_BLUE = 0
    anz_Magenta = 0
    anz_DarkOrange = 0
    anz_WHITE = 0

    anz_light_BLUE = 0
    anz_DarkOrange1 = 0  
    anz_lite_MAGENTA = 0
    anz_Rose = 0  
    anz_lRED = 0
    anz_OrangeRed = 0
    anz_darkOlive = 0
    anz_Olive = 0

    # Bild wird analysiert
    segmask, output = segment_image.segmentImage (fname, mask_points_values=True, show_bboxes=True)  #, output_image_name="2-testy.jpg")
    print ('    rois')
    a = segmask.get('rois')
    print (a)
    print (len(a))
    print ('    class_ids')
    # Noise Floor auswerten
    if len(a) == 0:
        nfmittelwert = 0.0
        if noisefloor == 1:
            for i_nf in range (300, 401):
                for j_nf in range (200, 301):
                    for k_nf in range (0, 3):
                        nfmittelwert = nfmittelwert + output[i_nf, j_nf, k_nf]
            cv2.circle(bg, (xa, 500 - int(nfmittelwert/5000)), 1 , Magenta, -1)
      #      Debugg Noisefloor
      #      print (nfmittelwert/5000)
      #      cv2.rectangle(output, (300, 200), (400, 300), YELLOW, 2)
      #      cv2.imshow("Bild fuer NF", output)
      #      cv2.waitKey(0)
      #      cv2.destroyAllWindows()

    #b = segmask.get('class_ids')
    b = segmask['class_ids'].astype('int')
    print (b)
    print (len(b))
    test  = np.zeros((100), np.int32)
    for itest in range (0, len(b)):
        test[itest] = b[itest]
        print (test[itest]*10)

    print ('    scores')
    c = segmask.get('scores')
    print (c)
    print (len(c))
    if len(c) > 0:
        print ('----masks')
        if len(b) > 1:  d = segmask.get('masks')
        if len(b) == 1:
            try:
                d = segmask['masks'].astype('int')
                print ('################################## len(b) war 1 ')
            except:
                d = segmask.get('masks')
     #  print('*********')
        print (len(d))
     #  print(d)
        anzahl = 0
        anzahl = len(d)
        print ('Anzahl Objekte  ', anzahl)

####### Konturen werden ausgewertet
        counter = 0
        color = Olive
    #   for i in d: cv2.polylines(output, i, isClosed, light_BLUE, dicke)
        for i in d:
            counter += 1
            print('#############   ', b[counter -1])
            if counter == 1:
                color = RED
                bg_RED  = i
            if counter == 2:
                color = GREEN
                bg_GREEN  = i
            if counter == 3:
                color = YELLOW
                bg_YELLOW  = i
            if counter == 4:
                color = BLUE
                bg_BLUE  = i
            if counter == 5:
                color = Magenta
                bg_Magenta  = i
            if counter == 6:
                color = DarkOrange
                bg_DarkOrange  = i
            if counter == 7:
                color = WHITE
                bg_WHITE  = i    
 
            if counter == 8:
                color =  light_BLUE
                bg_light_BLUE = i
            if counter == 9:
                color =  DarkOrange1
                bg_DarkOrange1 = i
            if counter == 10:
                color = lite_MAGENTA
                bg_lite_MAGENTA = i
            if counter == 11:
                color = Rose
                bg_Rose = i
            if counter == 12:
                color = lRED
                bg_lRED = i
            if counter == 13:
                color = OrangeRed
                bg_OrangeRed = i
            if counter == 14:
                color = darkOlive
                bg_darkOlive = i
            if counter == 15:
                color = Olive
                bg_Olive = i


        print('Anzahl der Bruchstuecke ')
        print(len(bg_RED))
        print(len(bg_GREEN))
        print(len(bg_YELLOW))
        print(len(bg_BLUE))
        print(len(bg_Magenta))
        print(len(bg_DarkOrange))
        print(len(bg_WHITE))
        print(len(bg_light_BLUE))
        # hier fehlt noch 9-15
        print(' >>>>>>>>> 1000 = leer')


        for o in range (1, anzahl +1):
            if o == 1:
                bg_temp = bg_RED
                col_temp = RED
                col_name = 'RED'
            if o == 2:
                bg_temp = bg_GREEN
                col_temp = GREEN
                col_name = 'GREEN'
            if o == 3:
                bg_temp = bg_YELLOW
                col_temp = YELLOW
                col_name = 'YELLOW'
            if o == 4:
                bg_temp = bg_BLUE
                col_temp = BLUE
                col_name = 'BLUE'
            if o == 5:
                bg_temp = bg_Magenta
                col_temp = Magenta
                col_name = 'Magenta'
            if o == 6:
                bg_temp = bg_DarkOrange
                col_temp = DarkOrange
                col_name = 'DarkOrange'
            if o == 7:
                bg_temp = bg_WHITE
                col_temp = WHITE
                col_name = 'WHITE'
########### hier fehlt noch 8-15
          #  if test[o-1] > 1: cv2.fillPoly(output, bg_temp, col_temp)

            laenge = len(bg_temp)
            print ('  Bruchstuecke von: ', col_name, '   ', laenge)
            counter = 0
            summe = 0
            xsumme = 0
            ysumme = 0
            for ii in bg_temp:
                print ('  Anzahl Wertepaare: ', len(ii))
                paare = np.zeros((len(ii),2), np.int32)
                if len(ii) >= 3:
                    counter = 0
                    for jj in ii:
                        paare[counter] = jj
                        counter += 1
                    cv2.fillPoly(output, [paare], col_temp)
                    pgon = Polygon(paare)
                    summe += pgon.area
                    print ('  Flaeche ', col_name, '      ', pgon.area)
                    mitte_x = round(pgon.centroid.x)
                    xsumme += mitte_x
                    mitte_y = round(pgon.centroid.y)
                    ysumme += mitte_y
                    print ('  Zentrum ', col_name, '  X= ', mitte_x, '  Y= ', mitte_y)
                if len(ii) < 3:
                    print (' >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>verworfen  ')
                    laenge -= 1
            if laenge > 1:
                print (' >>>>>> Mittelwert Zentrum: ', col_name, '  Xs= ', round(xsumme / laenge), '  Ys= ', round(ysumme / laenge))
                print (' >>>>>>>> Summe der Fläche: ', summe)
 
   
########### Dopplershift berechnen          
            if laenge > 0:
                org = (round(xsumme / laenge), round(ysumme / laenge))
                Ax = 930       # Projektionslini für die Dopplerschift.
                Ay = 609    
                Bx = 350
                By = 28  
                cv2.line(output, (Ax, Ay),(Bx, By), Magenta, 1)
                cv2.putText(output, ('Ax, Ay'), (Ax, Ay), font, fontScale, WHITE, fthickness, cv2.LINE_AA)

                dx = Bx - Ax
                dy = By - Ay
                cqu = dx*dx + dy*dy
                c_geo = m.sqrt(cqu)
         #      print ('  c_geo  ', c_geo)

                ux, uy = org

                dx = Bx - ux
                dy = By - uy
                a1_geo = m.sqrt(dx*dx + dy*dy)
         #      print ('  a1_geo  ',a1_geo)

                dx = Ax - ux
                dy = Ay - uy
                b1_geo = m.sqrt(dx*dx + dy*dy)
         #      print ('  b1_geo  ',b1_geo)
                try:    
                   cos_alpha = (b1_geo * b1_geo + cqu - a1_geo * a1_geo)/(2*b1_geo * c_geo) #Cosinussatz
                except:
                   cos_alpha = 0.7
         #      print ('  cos alpha  ', cos_alpha)
                try:
                    A_arc = m.acos(cos_alpha)
                except:
                    A_arc = 99
                sin_A = m.sin(A_arc)
                cos_A = m.cos(A_arc)
                A_deg = np.rad2deg(A_arc)
         #      print ('  Alpha  ',A_deg)
                hoehe1 = b1_geo * sin_A
         #      print ('  Hoehe: ', hoehe1)
                dopplershift =  round (m.sqrt(a1_geo * a1_geo - hoehe1 * hoehe1))    
                print ('  rel. Dopplershift: ', dopplershift)
############### Ende Dopplershift

                print (' >>>>>>>>>>>>>>>>>>>> Klasse: ', test[o-1])
                cv2.circle(output, org, 6 , WHITE, -1)
                if col_name == 'RED': cv2.circle(output, org, 3 , GREEN, -1)
                if col_name != 'RED': cv2.circle(output, org, 3 , RED, -1)
                fsize = ("{:5.0f}".format(summe))
                ds = ("{:3.0f}".format(dopplershift))

############ Flags fuer debug
                if test[o-1] == 1: starlink_was_there = True
                if test[o-1] == 3: meteor_was_there = True
                if c[o-1] < 0.8: klein_meteor_was_there = True
                if test[o-1] == 3 and summe > 10000: ue10000_was_there = True
                if (test[o-1] == 3) and (dopplershift > 550 and summe < 1000):  traeger_was_there = True

############ Echos im Bereich 200 bis 396 loggen. 196 (200 bis 396) entspricht 20 Sekunden in meinen Plots.
############ Ausser bei der Dopplershift ist dies der einzige Parameter. Den Wert kann man im Einzelschrittmodus ablesen.
 
                if (uy >= 200) and ( uy < 396) and (test[o-1] == 3) and (dopplershift > 300) and (dopplershift < 700) and (summe < 100000) and not \
                (dopplershift > 550 and summe < 1000):  # Stoerung siehe todo Doku
                    fontScale = 0.6
                    fsize = '++++++Flaeche:' + fsize + ' Dopplersh.:' + ds
                    print (' Score in Window ', c[o-1])

                    if (c[o-1] <= 1.00) and (c[o-1] > 0.99): score_100_99 += 1
                    if (c[o-1] <= 0.99) and (c[o-1] > 0.98): score_99_98 += 1
                    if (c[o-1] <= 0.98) and (c[o-1] > 0.97): score_98_97 += 1
                    if (c[o-1] <= 0.97) and (c[o-1] > 0.96): score_97_96 += 1
                    if (c[o-1] <= 0.96) and (c[o-1] > 0.95): score_96_95 += 1
                    if (c[o-1] <= 0.95) and (c[o-1] > 0.94): score_95_94 += 1
                    if (c[o-1] <= 0.94) and (c[o-1] > 0.93): score_94_93 += 1
                    if (c[o-1] <= 0.93) and (c[o-1] > 0.90): score_93_90 += 1                
                    if (c[o-1] <= 0.90) and (c[o-1] > 0.80): score_90_80 += 1
                    if (c[o-1] <= 0.80) and (c[o-1] > 0.72): score_80_70 += 1  
                    if (c[o-1] <= 0.72) and (c[o-1] > 0.00): score_70_00 += 1  
                   
                    offset_summe = summe - Baseline
                    if offset_summe <= 0:
                        offset_summe = 1
                        kleiner_Baseline_alle +=1

                    if (c[o-1] >= 0.72):  # nur hier loggen
                        y_t_color = GREEN              
                        if offset_summe == 1: kleiner_Baseline += 1
                        fl = int(495 -100 * m.log10(offset_summe))
                        globalcount += 1      
                        bg = cv2.circle(bg, (xa, fl), dicke , y_t_color, -1)
 
               ###### 1800 für 30 Minuten oder 2 Werte pro Stunde
               #  !  # 720 für 12 Minuten oder 5 Werte pro Stunde
               #  !  # 360 für 6 Minuten oder 10 Werte pro Stunde  
               ####### 180 für 3 Minuten oder 20 Werte pro Stunde
                        plot_count = m.trunc(ctime / 1800)
 
                        summe_3min[plot_count] += 1
                        fsumme_3min[plot_count] = fsumme_3min[plot_count] + summe

                        if (summe >  0)     and (summe < 500):    su1[plot_count] += 1
                        if (summe >= 500)   and (summe < 1000):   su2[plot_count] += 1
                        if (summe >= 1000)  and (summe < 3000):   su3[plot_count] += 1
                        if (summe >= 3000)  and (summe < 10000):  su4[plot_count] += 1
                        if (summe >= 10000) and (summe < 100000): su5[plot_count] += 1
                        if (c[o-1] >= 0.98): su6[plot_count] += 1  # score 0.98

                        summe_anz[int(ho)+1]  +=1
                        summe_fl[int(ho)+1] = summe_fl[int(ho)+1] + summe
                                                                 
################ Störung "Träger" innerhalb der 20 Sekunden
                if (uy >= 200) and ( uy < 396) and (dopplershift > 550 and summe < 1000):
                    fontScale = 0.6
                    fsize = '-x-T-x--Flaeche:' + fsize + ' Dopplersh.:' + ds
                    y_t_color = Rose
                    Err_count += 1
                    offset_summe = summe - Baseline
                    if offset_summe <= 0: offset_summe = 1
                    fl = int(495 -100 * m.log10(summe))
                    bg = cv2.circle(bg, (xa, fl), dicke , y_t_color, -1)      

 ################ Echos liegen zu nahe am Rand
                if (uy >= 200) and ( uy < 396) and (test[o-1] == 3) and ((dopplershift <= 300) or (dopplershift >= 700)):
                    fontScale = 0.6
                    fsize = '-x-W-x--Flaeche:' + fsize + ' Dopplersh.:' + ds
                    y_t_color = YELLOW
                    Err_count += 1
                    offset_summe = summe - Baseline
                    if offset_summe <= 0: offset_summe = 1
                    fl = int(495 -100 * m.log10(summe))
                    bg = cv2.circle(bg, (xa, fl), dicke , y_t_color, -1)                  
                   
################ Background innerhalb der 20 Sekunden loggen
                if (uy >= 200) and ( uy < 396) and (test[o-1] == 2) and (dopplershift >= 20): # Rand weg
                    fontScale = 0.6
                    fsize = '----R---Flaeche:' + fsize + ' Dopplersh.:' + ds
                    y_t_color = RED
                    BG_count += 1
                    offset_summe = summe - Baseline
                    if offset_summe <= 0: offset_summe = 1
                    fl = int(495 -100 * m.log10(offset_summe))
                    bg = cv2.circle(bg, (xa, fl), 2 , y_t_color, -1)    # 2 = dicke        
                 
################ Starlinks innerhalb der 20 Sekunden loggen
                if (uy >= 200) and ( uy < 396) and (test[o-1] == 1) and (c[o-1] >= 0.0):
                    fontScale = 0.6
                    fsize = '----B----Flaeche:' + fsize + ' Dopplersh.:' + ds
                    y_t_color = BLUE
                    Art_count += 1
                    offset_summe = summe - Baseline
                    if offset_summe <= 0: offset_summe = 1
                    fl = int(495 -100 * m.log10(offset_summe))
                    bg = cv2.circle(bg, (xa, fl), dicke , y_t_color, -1)  
                    summe_anz_Starlink[int(ho)+1]  +=1
             
################ Rest ausserhalb der 20 Sekunden beschriften
                if (uy < 200) or ( uy >= 396):  #196
                    fontScale = 0.6
                    fsize = '--------Flaeche:' + fsize + ' Dopplersh.:' + ds
                 
                ux, uy = org
                uy += 8
                cv2.putText(output, fsize, (ux, uy), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
                fontScale = 0.6
       
    #### Auswertebereich einzeichnen. 196 (200 bis 396) entspricht 20 Sekunden in meinen Plots.
    #### Ausser bei der Dopplershift ist dies der einzige Parameter. Den Wert kann man im Einzelschrittmodus ablesen.
    Ax1 = 300
    Ay1 = 200
    Bx1 = 1350
    By1 = 200
    cv2.line(output, (Ax1, Ay1),(Bx1, By1), light_BLUE, 1)
    Ax2 = 100
    Ay2 = 200 + 196
    Bx2 = 1150
    By2 = 200 + 196
    cv2.line(output, (Ax2, Ay2),(Bx2, By2), light_BLUE, 1)

    print ()
    print ('>>>>>>>>>>>>  Meteorechos (green) ', globalcount)  
    print ('>>>>>>>>>> Artifical Stars (blue) ', Art_count)  
    print ('>>>>>>>>>>>>>>>>> Backgound (red) ', BG_count)  
    print ('>am Rand/Stoerungen (yellow/rose) ', Err_count)

           
    if (debug == 1 and meteor_was_there == True) or ( debug == 2 and klein_meteor_was_there == True) or \
    (debug == 3 and starlink_was_there == True)  or ( debug == 4 and ue10000_was_there == True) or debug == 5 or (debug == 6 and traeger_was_there == True):
        cv2.imwrite("output.png", output)
        cv2.imshow("Output", output)
        cv2.waitKey(0)
        stream = cv2.imread(fname)
        cv2.imshow("Output", stream)
        cv2.imwrite("input.png", stream)
        cv2.waitKey(0) #################

cv2.line(bg,(1,1),(1,500),(WHITE),2)
cv2.line(bg,(1,499),(1900,499), WHITE,2)    # Skala

for grj in range (1,5):
    bg = cv2.line(bg,(0, grj * 100),(15, grj * 100), WHITE,2)   # Y- Ticks  
off = 4
cv2.putText(bg, '1', (5, 500-off), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg, '10', (5, 400-off), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg, '100', (5, 300-off), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg, '1000', (5, 200-off), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg, '10000', (5, 100-off), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg, '100000', (5, 20), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg, 'Size/Pixel', (15, 55), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg,'Time / UTC', (580, 543), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(bg,'WiSi 2023', (1350,543), font, 0.5, RED, fthickness, cv2.LINE_AA)

cv2.imshow('    ' + day +'. ' + Monat + Aufnahmejahr +' Logarithmus der Flaechen der Echos,' + sname, bg)
cv2.imwrite("bg.png", bg)


isscore = score_100_99 + score_99_98 +score_98_97 + score_97_96 + score_96_95 + score_95_94 + score_94_93 + score_93_90 + score_90_80 + score_80_70
sscore =  score_100_99 + score_99_98 +score_98_97 + score_97_96 + score_96_95 + score_95_94 + score_94_93 + score_93_90 + score_90_80 + score_80_70 + score_70_00

print()
print ('  Score Histogramm der Meteorechos')
print ('  100 % - 99 %  ', score_100_99)
print ('   99 % - 98 %  ', score_99_98)
print ('   98 % - 97 %  ', score_98_97)
print ('   97 % - 96 %  ', score_97_96)
print ('   96 % - 95 %  ', score_96_95)
print ('   95 % - 94 %  ', score_95_94)
print ('   94 % - 93 %  ', score_94_93)
print ('   93 % - 90 %  ', score_93_90)
print ('   90 % - 80 %  ', score_90_80)
print ('   80 % - 70 %  ', score_80_70)
print ('------------------------')
print ('   70 % Summe:   ', isscore)
print ('   kleiner ', Baseline, ':', kleiner_Baseline)
print()
print ('   70 % - 00 %  ', score_70_00)
print ('------------------------')
print ('   100 % Summe:  ', sscore)
print ('   kleiner ', Baseline, ':', kleiner_Baseline_alle)
print ()
print ('   Dauer der Analyse: ')
print ('   Start:',startzeit)
now = datetime.datetime.now()
print ('   Ende: ', now)
print ()


sugesamt = isscore

fl_max = 0
fl_max_i = 0
fl_sum = 0
print (' Histogramm Flaechen ')
for ihis in range (1,25):
    fl_sum = fl_sum + summe_fl[ihis]
    if fl_max < summe_fl[ihis]:
        fl_max = summe_fl[ihis]
        fl_max_i = ihis        
    print (summe_fl[ihis], end = ' |')
print ( '', end = "\r\n")

anz_max = 0
anz_max_i = 0
print (' Histogramm Anzahl ')
for ihis in range (1,25):
    if anz_max < summe_anz[ihis]:
        anz_max = summe_anz[ihis]
        anz_max_i = ihis
    print (summe_anz[ihis], end = ' |')
print ( '', end = "\r\n")


fontScale1 = 0.4
for ihis in range (1,25):
    cv2.rectangle(histogramm, (ihis*20, 250), ((ihis * 20) +10, 250 - int(summe_fl[ihis]/333.33/4)), RED, -1)  
    cv2.rectangle(histogramm, (ihis*20, 500), ((ihis * 20) +10, 500 - summe_anz[ihis]*3//2), YELLOW, -1)
    cv2.rectangle(histogramm, (ihis*20 +4, 500), ((ihis * 20) + 6, 500 - summe_anz_Starlink[ihis]*30//2), light_BLUE, -1)    # Starlink
    org = (int(ihis*19.9), 520)
    cv2.putText(histogramm, str(ihis-1), org, font, fontScale1, WHITE, fthickness, cv2.LINE_AA)
                                      # 250 -75 -75
cv2.line(histogramm,(30, 175),(490, 175), darkOlive, 1)
cv2.line(histogramm,(30, 100),(490, 100), darkOlive, 1)
cv2.putText(histogramm, '100k', (4, 175), font, fontScale1, Olive, fthickness, cv2.LINE_AA)
cv2.putText(histogramm, '200k',(4, 100), font, fontScale1, Olive, fthickness, cv2.LINE_AA)

                                      # 500 -75 -75
cv2.line(histogramm,(20, 425),(490, 425), darkOlive, 1)
cv2.line(histogramm,(20, 350),(490, 350), darkOlive, 1)
cv2.putText(histogramm, '50', (4, 425), font, fontScale1, Olive, fthickness, cv2.LINE_AA)
cv2.putText(histogramm, '5', (4, 438), font, fontScale1, light_BLUE, fthickness, cv2.LINE_AA)
cv2.putText(histogramm, '100', (4, 350), font, fontScale1, Olive, fthickness, cv2.LINE_AA)
cv2.putText(histogramm, '10', (4, 363), font, fontScale1, light_BLUE, fthickness, cv2.LINE_AA)

cv2.putText(histogramm, ' Summe Flaechen: '+str(int(fl_sum)), (10, 30), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(histogramm, ' max: '+ str(int(fl_max)) + ' um '+ str(fl_max_i - 1)+ ' h', (10, 50), font, fontScale, WHITE, fthickness, cv2.LINE_AA)

cv2.putText(histogramm, ' Anzahl: '+str(int(sugesamt)), (10, 280), font, fontScale, WHITE, fthickness, cv2.LINE_AA)
cv2.putText(histogramm, ' max: '+str(anz_max) + ' um ' + str(anz_max_i - 1) + ' h', (10, 300), font, fontScale, WHITE, fthickness, cv2.LINE_AA)

cv2.imshow('    ' + day +'. ' + Monat +' 2023, Histogramme, Zeit in UTC, Blau = Starlink', histogramm)

with open('datum.txt', 'w') as f:
    f.write(' Aufnahme ' + day + '. '+ Monat + ' 2023' + sname + '\n')
    f.write('         Zeit   Anzahl  Flaeche   500    1000   3000   10000   100000   Score 0.98' + '\n')

    for out_count in range (0, 48):                 # 48 für 30 Minuten, 120 für 12 Minuten, 240 für 6 Minuten, 480 für 3 Minuten
        out_i = ("{:6.0f}".format(out_count//(2)))  # 2 für  30 Minuten,   5 für 12 Minuten,  10 für 6 Minuten,  20 für 3 Minuten
        outn = ("{:8.0f}".format(summe_3min[out_count]))
        outf = ("{:8.0f}".format(round(fsumme_3min[out_count])))
        out1 = ("{:8.0f}".format(su1[out_count]))
        out2 = ("{:8.0f}".format(su2[out_count]))
        out3 = ("{:8.0f}".format(su3[out_count]))
        out4 = ("{:8.0f}".format(su4[out_count]))
        out5 = ("{:8.0f}".format(su5[out_count]))
        out6 = ("{:8.0f}".format(su6[out_count]))

        f.write('  UTC' + out_i + outn + outf + out1 + out2 + out3 + out4 + out5 + out6  + ' \n')
       
    f.write('\r\n')


with open('alt-datum.txt', 'w') as f:

    for out_count in range (0, 48):                      # 48 für 30 Minuten, 120 für 12 Minuten, 240 für 6 Minuten, 480 für 3 Minuten
        susi_i = ("{:8.0f}".format(out_count//(2)))      # 2 für  30 Minuten,   5 für 12 Minuten,  10 für 6 Minuten,  20 für 3 Minuten
        susi_3min = ("{:8.0f}".format(round(summe_3min[out_count]/1)))
        if out_count > 0: f.write('  ' + susi_i + susi_3min + '   \n')
        if out_count == 0: f.write('  ' + susi_i + susi_3min + '   Aufnahme ' + day + '. '+ Monat + ' 2023' + sname + '\n')
    f.write('\r\n')

    for out_count in range (0, 240):                  
        susi_i = ("{:8.0f}".format(out_count//(10)))  
        susi_3min = ("{:8.0f}".format(round(fsumme_3min[out_count]/1)))
        if out_count > 0: f.write('  ' + susi_i + susi_3min + '   \n')
        if out_count == 0: f.write('  ' + susi_i + susi_3min + '   Aufnahme ' + day + '. '+ Monat + ' 2023' + sname + '\n')
    f.write('\r\n')

print ('>>>>>>>>>>>>>>>>>>>>>>>>fertig ')
cv2.waitKey(0)
cv2.destroyAllWindows()
 

Anhänge

  • output.png
    output.png
    983,7 KB · Aufrufe: 37
Hier ist noch ein Beispiel mit Dopplershift:
Das Echo in 1output liegt nicht im Auswertebereich. Die (relative) Dopplershift ist 443.
Im Bild 2output ist es das rote Echo mit der fast identischen Dopplershift von 442. Dass die Werte nicht exakt gleich sind, liegt daran, dass es sich um eine neue Analyse an einem anderen Ort handelt. Manche Echos werden am Rand nicht erkannt, aber in der Mitte. In der Mitte ist die Detektion am besten, weil sich da die meisten Trainingsdaten befinden.
 

Anhänge

  • 1output.png
    1output.png
    971,4 KB · Aufrufe: 34
  • 2output.png
    2output.png
    977,7 KB · Aufrufe: 47
Guten Tag.
Zur Zeit sind viele Tagesströme unterwegs und es ist spannend, diese zu beobachten und mit den Daten zu experimentieren.
Hier werden 2 Tage im Mai 2023 (gestern und vorgestern) mit 2 Tagen im letzten Juni verglichen. Als erstes sieht man, dass es in den nächsten Wochen eine Zunahme geben sollte. Die maximalen Raten waren etwa 130 und 180 Echos / Stunde.
Der Vergleich zeigt auch, dass die Kerben um ~10 - 11 h UT im Mai nach dem gleichen Mechanismus entstehen, wie die Kerben in den Aritetiden-Daten von 2022: Im Mai befindet sich ziemlich genau ein Radiantenfeld aus NOC, SMA und OCE an der Position (bezogen auf die Sonne), wo sich im Juni ARI und ZPE befinden. Wie schon häufiger geschrieben, entstehen in einigen Strömen Kerben, wenn der Azuimut 180° beträgt.
Auch eine (Rest)-ETA Kerbe lässt sich um 7 - 8 h erkennen.
Der Berg um Mitternacht herum und die angedeuteten Kerben stammen wohl hauptsächlich von einem Radiantenfeld in der Gegend des Skorpions, siehe den Inset mit dem gelben Rand.
Eine Genehmigung zum Posten von CMOR Screenshots liegt vor. Zu berücksichtigen ist die Zeitverschiebung von 6 h zwischen den Standorten der Radar-Sender London Ontario in Kanada und Dijon in Frankreich.
Viele Grüße
Wilhelm
 

Anhänge

  • Mai12&13-2023-vs-Juni9&10-2022.png
    Mai12&13-2023-vs-Juni9&10-2022.png
    731,9 KB · Aufrufe: 40
Guten Tag.
Hier sieht man noch mal schön, wie zwei Radiantenfelder vor dem Radar vorbei ziehen. Es sollte also jetzt / gleich (~8 h UT) wieder ein Peak erscheinen.
Einen schönen Tag wünsche ich und
viele Grüße
Wilhelm
 

Anhänge

  • Test.png
    Test.png
    71,1 KB · Aufrufe: 41
Hallo Wilhelm,

danke fürs Update, ich komme auch langsam voran :)
Versuche gerade nachzuvollziehen wie du den Dopplerschift der ROIs berechnest. Kannst du das ganz kurz erläutern? Irgendwie Blick ich da nicht durch o_O

Viele Grüße
Stefanie
 
Hallo Stefanie,
sorry, das ist auch schwer zu verstehen, da das Programm nicht gut dokumentiert ist. Ich mache dir heute Abend noch eine Zeichnung dazu.

Das Programmteil ist ein Überbleibsel aus der alten Programmversion. Dort war das Auswerte-Zeitfenster schräg. Hier ist es einfacher: Das Zeitfenster, der Bereich zwischen den beiden horizontalen Linien, kann nun gerade sein, obwohl die Echos schräg verlaufen.

Die Laufrichtung der Signale ist im angehängten Plot gut an den Störträgern / Linien zu erkennen.
Die lila Linie (Ax, Ay) verläuft senkrecht zu der Bewegungsrichtung der Signale. Das sieht zwar optisch nicht wie ein rechter Winkel aus, lässt sich aber leicht mit einem Geodreieck prüfen.
Vom Schwerpunkt der Echos aus wird nun das Lot auf diese lila Linie gefällt. Dort wird dann die relative Dopplershift abgelesen.
Das geht mit dem Cosinussatz und Pythagoras. Heute Abend dokumentiere ich es noch mal grafisch.
Viele Grüße
Wilhelm
 

Anhänge

  • April13-test-final.png
    April13-test-final.png
    947,3 KB · Aufrufe: 37
Zuletzt bearbeitet:
Hallo Stefanie,
in der Skizze sind die Variablen bezeichnet. Die grüne Linie ist der Wert, den ich als relative Dopplershift ausgebe. Das geht bestimmt auch einfacher...
----------------
Es sind auch noch zwei Plots mit ein und demselben Echo angehängt. Da im Abstand von 20 s ein Plot gespeichert wird, der Plot aber länger als 60 s aufzeichnet, darf nur in einem 20 s langen Bereich geloggt werden.
An den Y-Werten kann man den Y-Vorschub zwischen den Plots von 196 Pixel ablesen. Dies ist dann auch der Abstand zwischen den beiden blauen Linien. Da bekommen die Echos im Einzelschrittmodus ein ++++ als Zeichen, dass sie richtig erkannt werden.
Der Ort für das Zeitfenster und für die Linie für die Dopplershift ist etwa in die Mitte gelegt. Die lila Linie ist so austariert, das beim Vorschub die Dopplershift konstant bleibt. Dann ist der Winkel zum Vorschub exakt 90°.
Viele Grüße
Wilhelm
 

Anhänge

  • Dopplershift-Variablen.JPG
    Dopplershift-Variablen.JPG
    438,4 KB · Aufrufe: 38
  • 1.png
    1.png
    1,3 MB · Aufrufe: 38
  • 2.png
    2.png
    1,4 MB · Aufrufe: 35
Zuletzt bearbeitet:
Oben