AttributeError: module 'tensorflow' has no attribute 'python'

Probleme bei der Installation?
Antworten
TomPyt
User
Beiträge: 17
Registriert: Mittwoch 29. Januar 2020, 11:28

Hallo,

im Rahmen dieses Tutorials (https://github.com/AntonMu/TrainYourOwnYOLO) versuche ich mit meinem Jetson Nano (Ubuntu 18.04) das unten gezeigte Programm auszuführen.
Leider tritt dieser Fehler auf:
AttributeError: module 'tensorflow' has no attribute 'python'
Hat jemand eine Idee, wie ich dieses Problem lösen kann?

Vielen Dank schon einmal im Voraus.
Tom

Code: Alles auswählen

# -*- coding: utf-8 -*-
"""
Class definition of YOLO_v3 style detection model on image and video
"""

import colorsys
import os
from timeit import default_timer as timer

import numpy as np
from keras.models import load_model
from keras.layers import Input
from PIL import Image, ImageFont, ImageDraw

from .yolo3.model import yolo_eval, yolo_body, tiny_yolo_body
from .yolo3.utils import letterbox_image
import os
from keras.utils import multi_gpu_model
import tensorflow.compat.v1 as tf
import tensorflow.python.keras.backend as K


tf.disable_eager_execution()


class YOLO(object):
    _defaults = {
        "model_path": "model_data/yolo.h5",
        "anchors_path": "model_data/yolo_anchors.txt",
        "classes_path": "model_data/coco_classes.txt",
        "score": 0.3,
        "iou": 0.45,
        "model_image_size": (416, 416),
        "gpu_num": 1,
    }

    @classmethod
    def get_defaults(cls, n):
        if n in cls._defaults:
            return cls._defaults[n]
        else:
            return "Unrecognized attribute name '" + n + "'"

    def __init__(self, **kwargs):
        self.__dict__.update(self._defaults)  # set up default values
        self.__dict__.update(kwargs)  # and update with user overrides
        self.class_names = self._get_class()
        self.anchors = self._get_anchors()
        self.sess = K.get_session()
        self.boxes, self.scores, self.classes = self.generate()# -*- coding: utf-8 -*-
"""
Class definition of YOLO_v3 style detection model on image and video
"""

import colorsys
import os
from timeit import default_timer as timer

import numpy as np
from keras.models import load_model
from keras.layers import Input
from PIL import Image, ImageFont, ImageDraw


    def _get_class(self):
        classes_path = os.path.expanduser(self.classes_path)
        with open(classes_path) as f:
            class_names = f.readlines()
        class_names = [c.strip() for c in class_names]
        return class_names

    def _get_anchors(self):
        anchors_path = os.path.expanduser(self.anchors_path)
        with open(anchors_path) as f:
            anchors = f.readline()
        anchors = [float(x) for x in anchors.split(",")]
        return np.array(anchors).reshape(-1, 2)

    def generate(self):
        model_path = os.path.expanduser(self.model_path)
        assert model_path.endswith(".h5"), "Keras model or weights must be a .h5 file."

        # Load model, or construct model and load weights.
        start = timer()
        num_anchors = len(self.anchors)
        num_classes = len(self.class_names)
        is_tiny_version = num_anchors == 6  # default setting
        try:
            self.yolo_model = load_model(model_path, compile=False)
        except:
            self.yolo_model = (
                tiny_yolo_body(
                    Input(shape=(None, None, 3)), num_anchors // 2, num_classes
                )
                if is_tiny_version
                else yolo_body(
                    Input(shape=(None, None, 3)), num_anchors // 3, num_classes
                )
            )
            self.yolo_model.load_weights(
                self.model_path
            )  # make sure model, anchors and classes match
        else:
            assert self.yolo_model.layers[-1].output_shape[-1] == num_anchors / len(
                self.yolo_model.output
            ) * (
                num_classes + 5
            ), "Mismatch between model and given anchor and class sizes"

        end = timer()
        print(
            "{} model, anchors, and classes loaded in {:.2f}sec.".format(
                model_path, end - start
            )
        )

        # Generate colors for drawing bounding boxes.
        if len(self.class_names) == 1:
            self.colors = ["GreenYellow"]
        else:
            hsv_tuples = [
                (x / len(self.class_names), 1.0, 1.0)
                for x in range(len(self.class_names))
            ]
            self.colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples))
            self.colors = list(
                map(
                    lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)),
                    self.colors,
                )
            )
            np.random.seed(10101)  # Fixed seed for consistent colors across runs.
            np.random.shuffle(
                self.colors
            )  # Shuffle colors to decorrelate adjacent classes.
            np.random.seed(None)  # Reset seed to default.

        # Generate output tensor targets for filtered bounding boxes.
        self.input_image_shape = K.placeholder(shape=(2,))
        if self.gpu_num >= 2:
            self.yolo_model = multi_gpu_model(self.yolo_model, gpus=self.gpu_num)
        boxes, scores, classes = yolo_eval(
            self.yolo_model.output,
            self.anchors,
            len(self.class_names),
            self.input_image_shape,
            score_threshold=self.score,
            iou_threshold=self.iou,
        )
        return boxes, scores, classes

    def detect_image(self, image, show_stats=True):
        start = timer()

        if self.model_image_size != (None, None):
            assert self.model_image_size[0] % 32 == 0, "Multiples of 32 required"
            assert self.model_image_size[1] % 32 == 0, "Multiples of 32 required"
            boxed_image = letterbox_image(image, tuple(reversed(self.model_image_size)))
        else:
            new_image_size = (
                image.width - (image.width % 32),
                image.height - (image.height % 32),
            )
            boxed_image = letterbox_image(image, new_image_size)
        image_data = np.array(boxed_image, dtype="float32")
        if show_stats:
            print(image_data.shape)
        image_data /= 255.0
        image_data = np.expand_dims(image_data, 0)  # Add batch dimension.

        out_boxes, out_scores, out_classes = self.sess.run(
            [self.boxes, self.scores, self.classes],
            feed_dict={
                self.yolo_model.input: image_data,
                self.input_image_shape: [image.size[1], image.size[0]],
                K.learning_phase(): 0,
            },
        )
        if show_stats:
            print("Found {} boxes for {}".format(len(out_boxes), "img"))
        out_prediction = []

        font_path = os.path.join(os.path.dirname(__file__), "font/FiraMono-Medium.otf")
        font = ImageFont.truetype(
            font=font_path, size=np.floor(3e-2 * image.size[1] + 0.5).astype("int32")
        )
        thickness = (image.size[0] + image.size[1]) // 300

        for i, c in reversed(list(enumerate(out_classes))):
            predicted_class = self.class_names[c]
            box = out_boxes[i]
            score = out_scores[i]

            label = "{} {:.2f}".format(predicted_class, score)
            draw = ImageDraw.Draw(image)
            label_size = draw.textsize(label, font)

            top, left, bottom, right = box
            top = max(0, np.floor(top + 0.5).astype("int32"))
            left = max(0, np.floor(left + 0.5).astype("int32"))
            bottom = min(image.size[1], np.floor(bottom + 0.5).astype("int32"))
            right = min(image.size[0], np.floor(right + 0.5).astype("int32"))

            # image was expanded to model_image_size: make sure it did not pick
            # up any box outside of original image (run into this bug when
            # lowering confidence threshold to 0.01)
            if top > image.size[1] or right > image.size[0]:
                continue
            if show_stats:
                print(label, (left, top), (right, bottom))

            # output as xmin, ymin, xmax, ymax, class_index, confidence
            out_prediction.append([left, top, right, bottom, c, score])

            if top - label_size[1] >= 0:
                text_origin = np.array([left, top - label_size[1]])
            else:
                text_origin = np.array([left, bottom])

            # My kingdom for a good redistributable image drawing library.
            for i in range(thickness):
                draw.rectangle(
                    [left + i, top + i, right - i, bottom - i], outline=self.colors[c]
                )
            draw.rectangle(
                [tuple(text_origin), tuple(text_origin + label_size)],
                fill=self.colors[c],
            )

            draw.text(text_origin, label, fill=(0, 0, 0), font=font)
            del draw

        end = timer()
        if show_stats:
            print("Time spent: {:.3f}sec".format(end - start))
        return out_prediction, image

    def close_session(self):
        self.sess.close()


def detect_video(yolo, video_path, output_path=""):
    import cv2

    vid = cv2.VideoCapture(video_path)
    if not vid.isOpened():
        raise IOError("Couldn't open webcam or video")
    video_FourCC = cv2.VideoWriter_fourcc(*"mp4v")  # int(vid.get(cv2.CAP_PROP_FOURCC))
    video_fps = vid.get(cv2.CAP_PROP_FPS)
    video_size = (
        int(vid.get(cv2.CAP_PROP_FRAME_WIDTH)),
        int(vid.get(cv2.CAP_PROP_FRAME_HEIGHT)),
    )
    isOutput = True if output_path != "" else False
    if isOutput:
        print(
            "Processing {} with frame size {} at {:.1f} FPS".format(
                os.path.basename(video_path), video_size, video_fps
            )
        )
        # print("!!! TYPE:", type(output_path), type(video_FourCC), type(video_fps), type(video_size))
        out = cv2.VideoWriter(output_path, video_FourCC, video_fps, video_size)
    accum_time = 0
    curr_fps = 0
    fps = "FPS: ??"
    prev_time = timer()
    while vid.isOpened():
        return_value, frame = vid.read()
        if not return_value:
            break
        # opencv images are BGR, translate to RGB
        frame = frame[:, :, ::-1]
        image = Image.fromarray(frame)
        out_pred, image = yolo.detect_image(image, show_stats=False)
        result = np.asarray(image)
        curr_time = timer()
        exec_time = curr_time - prev_time
        prev_time = curr_time
        accum_time = accum_time + exec_time
        curr_fps = curr_fps + 1
        if accum_time > 1:
            accum_time = accum_time - 1
            fps = "FPS: " + str(curr_fps)
            curr_fps = 0
        cv2.putText(
            result,
            text=fps,
            org=(3, 15),
            fontFace=cv2.FONT_HERSHEY_SIMPLEX,
            fontScale=0.50,
            color=(255, 0, 0),
            thickness=2,
        )
        # cv2.namedWindow("result", cv2.WINDOW_NORMAL)
        # cv2.imshow("result", result)
        if isOutput:
            out.write(result[:, :, ::-1])
        # if cv2.waitKey(1) & 0xFF == ord('q'):
        #     break
    vid.release()
    out.release()
    # yolo.close_session()
Benutzeravatar
__blackjack__
User
Beiträge: 12984
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@TomPyt: Das kann nicht sein denn das läuft gar nicht. Das kommt nicht am Compiler vorbei weil da mitten in der Klassendefinition Code falsch eingerückt ist und da wohl auch nicht hingehört.

Ansonsten wäre ein kompletter Traceback nötig, es sei denn Du erwartest jetzt tatsächlich das wir raten wo in den 300 Zeilen Code diese Ausnahme wohl auftreten könnte.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
TomPyt
User
Beiträge: 17
Registriert: Mittwoch 29. Januar 2020, 11:28

Also nach der Eingabe von

Code: Alles auswählen

python3 Minimal_Example.py
in einem Terminal Window erscheint eine Ausgabe und das hier sind die letzten Zeilen davon:

Code: Alles auswählen

    import tensorflow.python.keras.backend as K
AttributeError: module 'tensorflow' has no attribute 'python'
Detected Cat Faces in 12.2 seconds
Bezüglich des falsch eingerückten Codes wundert es mich. Ich habe den kompletten Code 1:1 kopiert bzw. von GitHub übernommen.
Dort sind mir zumindest keine Kommentare bzgl. des falschen Einrückens aufgefallen. Und ich selber kenne mich nicht gut genug aus, um manche Fehler zu erkennen.
[...] es sei denn Du erwartest jetzt tatsächlich das wir raten wo in den 300 Zeilen Code diese Ausnahme wohl auftreten könnte.
Da ich mich wie gesagt nicht so gut auskenne, habe ich gehofft, dass mir evtl. jemand helfen kann. Für das Fragen nach Hilfe ist ein Forum doch unter anderem da.
Theoretisch hätte es ja eine ganz einfache Lösung geben können. Oder jemand anderes hatte schon das gleiche bzw. ein ähnliches Problem, dass er/sie auf eine bestimmte Weise lösen konnte. Das dies scheinbar nicht der Fall ist, konnte ich vorher leider nicht wissen.
Benutzeravatar
__blackjack__
User
Beiträge: 12984
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@TomPyt: Nochmal, diese Ausgabe kannst Du nicht von dem gezeigten Quelltext haben weil der nicht läuft, weil der nicht am Compiler vorbei kommt:

Code: Alles auswählen

$ python3 forum19.py 
  File "forum19.py", line 65
    def _get_class(self):
    ^
IndentationError: unexpected indent
Da steht mitten in der Klassendefinition Code der da *offensichtlich* so nicht hingehört, denn es gibt auch nicht wirklich eine für den Compiler korrekte Einrückung die Sinn machen würde.

Und das solltest Du sehen können. Wenn Du das nicht siehst, solltest Du einen Schritt zurück machen und Python-Grundlagen lernen. Denn wenn man mit der in der Python für die Syntax wichtigen Einrückung nicht klar kommt kann man kein Python-Programm schreiben.

Und jetzt hast Du eine Zeile mehr von dem Traceback gezeigt, aber Du solltest bei Ausnahmen immer den *gesamten* Traceback zeigen. Da stecken Informationen drin an denen man mindestens mal ablesen kann *wo* die Ausnahme auftritt und welche Aufrufe dazu geführt haben. Das ist in der Regel wichtig und in der Regel auch nicht so einfach am Code abzulesen wie in diesem Fall, denn die Ausnahme wird oft ja nicht im eigenen Code ausgelöst, sondern in irgendeiner Bibliothek.

Ja das Forum ist für Fragen da, aber um Fragen beantworten zu können müssen halt auch ausreichend Informationen geliefert werden. Wenn jemand 300 Zeilen Code und nur die letzte Zeile von einem Traceback liefert, schaue ich da gar nicht erst in den Code sondern stelle eine Nachfrage nach dem Traceback damit ich nicht raten/suchen muss was der Fragesteller schon sehr einfach hätte mitliefern können.

Es kann auch nicht sein, dass das `tensorfow.python`-Modul nicht existiert was in der Zeile vorkommt, denn das hätte zu einem `ImportError` geführt. Es muss also irgendwo anders ein `python`-Modul (nicht) geben, wo der Code aber eines erwartet.

Wie danach noch eine Textausgabe anscheinend von dem Programm kommen kann ist mir auch ein Rätsel.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
TomPyt
User
Beiträge: 17
Registriert: Mittwoch 29. Januar 2020, 11:28

Ok, dann hier noch weitere Infos. Evtl. helfen die.
(Nochmal als Nachtrag: Der Code, der in meinem ersten Kommentar gezeigt ist, entspricht dem Programm yolo.py)


Hier ist dann erstmal der Code, den ich mit der Eingabe

Code: Alles auswählen

python3 Minimal_Example.py
ausführe.

Code: Alles auswählen

import os
import subprocess
import time
import sys


def make_call_string(arglist):
    result_string = ""
    for arg in arglist:
        result_string += "".join(["--", arg[0], " ", arg[1], " "])
    return result_string


root_folder = os.path.dirname(os.path.abspath(__file__))
data_folder = os.path.join(root_folder, "Data")
model_folder = os.path.join(data_folder, "Model_Weights")
image_folder = os.path.join(data_folder, "Source_Images")
input_folder = os.path.join(image_folder, "Test_Images")
output_folder = os.path.join(image_folder, "Test_Image_Detection_Results")


if not os.path.exists(output_folder):
    os.mkdir(output_folder)

# First download the pre-trained weights
download_script = os.path.join(model_folder, "Download_Weights.py")

if not os.path.isfile(os.path.join(model_folder, "trained_weights_final.h5")):
    print("\n", "Downloading Pretrained Weights", "\n")
    start = time.time()
    call_string = " ".join(
        [
            "python",
            download_script,
            "1MGXAP_XD_w4OExPP10UHsejWrMww8Tu7",
            os.path.join(model_folder, "trained_weights_final.h5"),
        ]
    )

    subprocess.call(call_string, shell=True)

    end = time.time()
    print("Downloaded Pretrained Weights in {0:.1f} seconds".format(end - start), "\n")

# Now run the cat face detector
detector_script = os.path.join(
    os.path.dirname(os.path.abspath(__file__)), "3_Inference", "Detector.py"
)


result_file = os.path.join(output_folder, "Detection_Results.csv")
model_weights = os.path.join(model_folder, "trained_weights_final.h5")
classes_file = os.path.join(model_folder, "data_classes.txt")
anchors = os.path.join(
    root_folder, "2_Training", "src", "keras_yolo3", "model_data", "yolo_anchors.txt"
)

arglist = [
    ["input_path", input_folder],
    ["classes", classes_file],
    ["output", output_folder],
    ["yolo_model", model_weights],
    ["box_file", result_file],
    ["anchors", anchors],
    ["file_types", ".jpg .jpeg .png"],
]
call_string = " ".join(["python", detector_script, make_call_string(arglist)])

print("Detecting Cat Faces by calling: \n\n", call_string, "\n")
start = time.time()
subprocess.call(call_string, shell=True)
end = time.time()
print("Detected Cat Faces in {0:.1f} seconds".format(end - start))
Dies ist dann die Ausgabe im Terminal Window:

Code: Alles auswählen

Detecting Cat Faces by calling: 

 python /home/christopher/TrainYourOwnYOLO/trainyourownyolo/3_Inference/Detector.py --input_path /home/christopher/TrainYourOwnYOLO/trainyourownyolo/Data/Source_Images/Test_Images --classes /home/christopher/TrainYourOwnYOLO/trainyourownyolo/Data/Model_Weights/data_classes.txt --output /home/christopher/TrainYourOwnYOLO/trainyourownyolo/Data/Source_Images/Test_Image_Detection_Results --yolo_model /home/christopher/TrainYourOwnYOLO/trainyourownyolo/Data/Model_Weights/trained_weights_final.h5 --box_file /home/christopher/TrainYourOwnYOLO/trainyourownyolo/Data/Source_Images/Test_Image_Detection_Results/Detection_Results.csv --anchors /home/christopher/TrainYourOwnYOLO/trainyourownyolo/2_Training/src/keras_yolo3/model_data/yolo_anchors.txt --file_types .jpg .jpeg .png  

Using TensorFlow backend.
2020-09-24 13:52:21.696919: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcudart.so.10.0
2020-09-24 13:52:25.390161: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libnvinfer.so.6
2020-09-24 13:52:25.392040: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libnvinfer_plugin.so.6
Traceback (most recent call last):
  File "/home/christopher/TrainYourOwnYOLO/trainyourownyolo/3_Inference/Detector.py", line 21, in <module>
    from keras_yolo3.yolo import YOLO, detect_video
  File "/home/christopher/TrainYourOwnYOLO/trainyourownyolo/2_Training/src/keras_yolo3/yolo.py", line 20, in <module>
    import tensorflow.python.keras.backend as K
AttributeError: module 'tensorflow' has no attribute 'python'
Detected Cat Faces in 12.2 seconds
Hilft das weiter?
Benutzeravatar
sparrow
User
Beiträge: 4144
Registriert: Freitag 17. April 2009, 10:28

Das ist ein Script, das Dinge tut und dann ein anderes Script aufruft. Der Fehler ist in dem aufgerufenen (nicht importierten!) Script.
Benutzeravatar
__blackjack__
User
Beiträge: 12984
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@TomPyt: Wenn der Quelltext im ersten Beitrag dem Programm ``yolo.py`` entspricht, dann hat das nichts mit der Fehlermeldung zu tun, denn wie bereits gesagt ist das überhaupt gar nicht lauffähig und führt zu der Ausnahme die ich ja bereits gezeigt habe.

Der Code im ersten Beitrag ist ganz sicher nicht der Inhalt von der Datei ``/home/christopher/TrainYourOwnYOLO/trainyourownyolo/2_Training/src/keras_yolo3/yolo.py``, denn die wird ja offenbar ausgeführt, konnte also kompiliert werden.

Das ``Minimal_Example.py`` sieht ziemlich gruselig aus. Insbesondere sehe ich nicht warum man da eine unnötige Shell bei `subprocess.call()` dazuwischen schalten sollte. Gib die Argumente als Liste und bastel da nicht eine Zeichenkette zusammen die von der Shell dann wieder auseinandergenommen werden muss. Das ist nur eine unnötige Fehlerquelle.

Statt `os.path` verwendet man in neuem Code besser das `pathlib`-Modul. Und anstelle von `subprocess.call()` besser `subprocess.run()`.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
TomPyt
User
Beiträge: 17
Registriert: Mittwoch 29. Januar 2020, 11:28

Also das Problem muss irgendwo auf dem Jetson Nano liegen bzw. mit diesem zusammenhängen.
Ich habe den gesamten Code von GitHub jetzt noch einmal auf meinen Windows Rechner geladen, bin dann den beschriebenen Anweisungen gefolgt und habe anschließend

Code: Alles auswählen

python Minimal_Example.py
ausgeführt. Das ist direkt fehlerfrei durchgelaufen.

Eventuell setze ich auf dem Nano nochmal alles auf Anfang und dann mal schauen.
TomPyt
User
Beiträge: 17
Registriert: Mittwoch 29. Januar 2020, 11:28

__blackjack__ hat geschrieben: Donnerstag 24. September 2020, 15:08 @TomPyt: Wenn der Quelltext im ersten Beitrag dem Programm ``yolo.py`` entspricht, dann hat das nichts mit der Fehlermeldung zu tun, denn wie bereits gesagt ist das überhaupt gar nicht lauffähig und führt zu der Ausnahme die ich ja bereits gezeigt habe.

Der Code im ersten Beitrag ist ganz sicher nicht der Inhalt von der Datei ``/home/christopher/TrainYourOwnYOLO/trainyourownyolo/2_Training/src/keras_yolo3/yolo.py``, denn die wird ja offenbar ausgeführt, konnte also kompiliert werden.

Das ``Minimal_Example.py`` sieht ziemlich gruselig aus. Insbesondere sehe ich nicht warum man da eine unnötige Shell bei `subprocess.call()` dazuwischen schalten sollte. Gib die Argumente als Liste und bastel da nicht eine Zeichenkette zusammen die von der Shell dann wieder auseinandergenommen werden muss. Das ist nur eine unnötige Fehlerquelle.

Statt `os.path` verwendet man in neuem Code besser das `pathlib`-Modul. Und anstelle von `subprocess.call()` besser `subprocess.run()`.

Generell erstmal danke für die Rückmeldungen.
Also ich habe den Code ja nicht selber geschrieben, aber die Tipps von oben nehme ich gerne mit.

Der Code im ersten Beitrag ist tatsächlich nicht der korrekte Code von yolo.py .... das war dann mal ein Fehlstart in meine Frage...
Nachfolgender Code ist der richtige. Der ist recht ähnlich, aber eben nicht gleich.

Code: Alles auswählen

# -*- coding: utf-8 -*-
"""
Class definition of YOLO_v3 style detection model on image and video
"""

import colorsys
import os
from timeit import default_timer as timer

import numpy as np
from keras.models import load_model
from keras.layers import Input
from PIL import Image, ImageFont, ImageDraw

from .yolo3.model import yolo_eval, yolo_body, tiny_yolo_body
from .yolo3.utils import letterbox_image
import os
from keras.utils import multi_gpu_model
import tensorflow.compat.v1 as tf
import tensorflow.python.keras.backend as K


tf.disable_eager_execution()


class YOLO(object):
    _defaults = {
        "model_path": "model_data/yolo.h5",
        "anchors_path": "model_data/yolo_anchors.txt",
        "classes_path": "model_data/coco_classes.txt",
        "score": 0.3,
        "iou": 0.45,
        "model_image_size": (416, 416),
        "gpu_num": 1,
    }

    @classmethod
    def get_defaults(cls, n):
        if n in cls._defaults:
            return cls._defaults[n]
        else:
            return "Unrecognized attribute name '" + n + "'"

    def __init__(self, **kwargs):
        self.__dict__.update(self._defaults)  # set up default values
        self.__dict__.update(kwargs)  # and update with user overrides
        self.class_names = self._get_class()
        self.anchors = self._get_anchors()
        self.sess = K.get_session()
        self.boxes, self.scores, self.classes = self.generate()

    def _get_class(self):
        classes_path = os.path.expanduser(self.classes_path)
        with open(classes_path) as f:
            class_names = f.readlines()
        class_names = [c.strip() for c in class_names]
        return class_names

    def _get_anchors(self):
        anchors_path = os.path.expanduser(self.anchors_path)
        with open(anchors_path) as f:
            anchors = f.readline()
        anchors = [float(x) for x in anchors.split(",")]
        return np.array(anchors).reshape(-1, 2)

    def generate(self):
        model_path = os.path.expanduser(self.model_path)
        assert model_path.endswith(".h5"), "Keras model or weights must be a .h5 file."

        # Load model, or construct model and load weights.
        start = timer()
        num_anchors = len(self.anchors)
        num_classes = len(self.class_names)
        is_tiny_version = num_anchors == 6  # default setting
        try:
            self.yolo_model = load_model(model_path, compile=False)
        except:
            self.yolo_model = (
                tiny_yolo_body(
                    Input(shape=(None, None, 3)), num_anchors // 2, num_classes
                )
                if is_tiny_version
                else yolo_body(
                    Input(shape=(None, None, 3)), num_anchors // 3, num_classes
                )
            )
            self.yolo_model.load_weights(
                self.model_path
            )  # make sure model, anchors and classes match
        else:
            assert self.yolo_model.layers[-1].output_shape[-1] == num_anchors / len(
                self.yolo_model.output
            ) * (
                num_classes + 5
            ), "Mismatch between model and given anchor and class sizes"

        end = timer()
        print(
            "{} model, anchors, and classes loaded in {:.2f}sec.".format(
                model_path, end - start
            )
        )

        # Generate colors for drawing bounding boxes.
        if len(self.class_names) == 1:
            self.colors = ["GreenYellow"]
        else:
            hsv_tuples = [
                (x / len(self.class_names), 1.0, 1.0)
                for x in range(len(self.class_names))
            ]
            self.colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples))
            self.colors = list(
                map(
                    lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)),
                    self.colors,
                )
            )
            np.random.seed(10101)  # Fixed seed for consistent colors across runs.
            np.random.shuffle(
                self.colors
            )  # Shuffle colors to decorrelate adjacent classes.
            np.random.seed(None)  # Reset seed to default.

        # Generate output tensor targets for filtered bounding boxes.
        self.input_image_shape = K.placeholder(shape=(2,))
        if self.gpu_num >= 2:
            self.yolo_model = multi_gpu_model(self.yolo_model, gpus=self.gpu_num)
        boxes, scores, classes = yolo_eval(
            self.yolo_model.output,
            self.anchors,
            len(self.class_names),
            self.input_image_shape,
            score_threshold=self.score,
            iou_threshold=self.iou,
        )
        return boxes, scores, classes

    def detect_image(self, image, show_stats=True):
        start = timer()

        if self.model_image_size != (None, None):
            assert self.model_image_size[0] % 32 == 0, "Multiples of 32 required"
            assert self.model_image_size[1] % 32 == 0, "Multiples of 32 required"
            boxed_image = letterbox_image(image, tuple(reversed(self.model_image_size)))
        else:
            new_image_size = (
                image.width - (image.width % 32),
                image.height - (image.height % 32),
            )
            boxed_image = letterbox_image(image, new_image_size)
        image_data = np.array(boxed_image, dtype="float32")
        if show_stats:
            print(image_data.shape)
        image_data /= 255.0
        image_data = np.expand_dims(image_data, 0)  # Add batch dimension.

        out_boxes, out_scores, out_classes = self.sess.run(
            [self.boxes, self.scores, self.classes],
            feed_dict={
                self.yolo_model.input: image_data,
                self.input_image_shape: [image.size[1], image.size[0]],
                K.learning_phase(): 0,
            },
        )
        if show_stats:
            print("Found {} boxes for {}".format(len(out_boxes), "img"))
        out_prediction = []

        font_path = os.path.join(os.path.dirname(__file__), "font/FiraMono-Medium.otf")
        font = ImageFont.truetype(
            font=font_path, size=np.floor(3e-2 * image.size[1] + 0.5).astype("int32")
        )
        thickness = (image.size[0] + image.size[1]) // 300

        for i, c in reversed(list(enumerate(out_classes))):
            predicted_class = self.class_names[c]
            box = out_boxes[i]
            score = out_scores[i]

            label = "{} {:.2f}".format(predicted_class, score)
            draw = ImageDraw.Draw(image)
            label_size = draw.textsize(label, font)

            top, left, bottom, right = box
            top = max(0, np.floor(top + 0.5).astype("int32"))
            left = max(0, np.floor(left + 0.5).astype("int32"))
            bottom = min(image.size[1], np.floor(bottom + 0.5).astype("int32"))
            right = min(image.size[0], np.floor(right + 0.5).astype("int32"))

            # image was expanded to model_image_size: make sure it did not pick
            # up any box outside of original image (run into this bug when
            # lowering confidence threshold to 0.01)
            if top > image.size[1] or right > image.size[0]:
                continue
            if show_stats:
                print(label, (left, top), (right, bottom))

            # output as xmin, ymin, xmax, ymax, class_index, confidence
            out_prediction.append([left, top, right, bottom, c, score])

            if top - label_size[1] >= 0:
                text_origin = np.array([left, top - label_size[1]])
            else:
                text_origin = np.array([left, bottom])

            # My kingdom for a good redistributable image drawing library.
            for i in range(thickness):
                draw.rectangle(
                    [left + i, top + i, right - i, bottom - i], outline=self.colors[c]
                )
            draw.rectangle(
                [tuple(text_origin), tuple(text_origin + label_size)],
                fill=self.colors[c],
            )

            draw.text(text_origin, label, fill=(0, 0, 0), font=font)
            del draw

        end = timer()
        if show_stats:
            print("Time spent: {:.3f}sec".format(end - start))
        return out_prediction, image

    def close_session(self):
        self.sess.close()


def detect_video(yolo, video_path, output_path=""):
    import cv2

    vid = cv2.VideoCapture(video_path)
    if not vid.isOpened():
        raise IOError("Couldn't open webcam or video")
    video_FourCC = cv2.VideoWriter_fourcc(*"mp4v")  # int(vid.get(cv2.CAP_PROP_FOURCC))
    video_fps = vid.get(cv2.CAP_PROP_FPS)
    video_size = (
        int(vid.get(cv2.CAP_PROP_FRAME_WIDTH)),
        int(vid.get(cv2.CAP_PROP_FRAME_HEIGHT)),
    )
    isOutput = True if output_path != "" else False
    if isOutput:
        print(
            "Processing {} with frame size {} at {:.1f} FPS".format(
                os.path.basename(video_path), video_size, video_fps
            )
        )
        # print("!!! TYPE:", type(output_path), type(video_FourCC), type(video_fps), type(video_size))
        out = cv2.VideoWriter(output_path, video_FourCC, video_fps, video_size)
    accum_time = 0
    curr_fps = 0
    fps = "FPS: ??"
    prev_time = timer()
    while vid.isOpened():
        return_value, frame = vid.read()
        if not return_value:
            break
        # opencv images are BGR, translate to RGB
        frame = frame[:, :, ::-1]
        image = Image.fromarray(frame)
        out_pred, image = yolo.detect_image(image, show_stats=False)
        result = np.asarray(image)
        curr_time = timer()
        exec_time = curr_time - prev_time
        prev_time = curr_time
        accum_time = accum_time + exec_time
        curr_fps = curr_fps + 1
        if accum_time > 1:
            accum_time = accum_time - 1
            fps = "FPS: " + str(curr_fps)
            curr_fps = 0
        cv2.putText(
            result,
            text=fps,
            org=(3, 15),
            fontFace=cv2.FONT_HERSHEY_SIMPLEX,
            fontScale=0.50,
            color=(255, 0, 0),
            thickness=2,
        )
        # cv2.namedWindow("result", cv2.WINDOW_NORMAL)
        # cv2.imshow("result", result)
        if isOutput:
            out.write(result[:, :, ::-1])
        # if cv2.waitKey(1) & 0xFF == ord('q'):
        #     break
    vid.release()
    out.release()
    # yolo.close_session()
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Ich vermute deine Probleme haben etwas mit verschiedenen Versionen von Tensorflow zu tun.
Der Code ist vermutlich für Tensorflow 1.x und das separate Keras entwickelt worden.
Wenn du nicht explizit TF 1.x installiert hast, hast du vermutlich TF 2.x auf deinem System.
Darin ist Keras jetzt integriert als tensorflow.keras.

Eventuell hilfreicher Link:
https://www.google.com/search?&q=module ... 8&oe=UTF-8
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
TomPyt
User
Beiträge: 17
Registriert: Mittwoch 29. Januar 2020, 11:28

Hallo Thomas,

vielen Dank für den Link.
Ich werde dort mal nach Lösungsvorschlägen gucken und hoffentlich finde ich etwas Hilfreiches für mein Problem.
Antworten