[PYTHON] Bildverarbeitung mit MyHDL

Was ist MyHDL?

http://www.myhdl.org/ Eine Bibliothek zur Modellierung von Hardware in Python, entwickelt in. Dieses Mal habe ich versucht, die Bildverarbeitung mit MyHDL zu modellieren. In Bezug auf die Schichten fühlte ich mich in der gleichen Position wie System C.

Alle Quellen sind hier oben. https://github.com/natsutan/computervision/tree/master/LOCV/chap5

Beschreibung der Bildverarbeitung

Ich habe versucht, einem bestimmten Bereich des Eingabebildes eine einfache Unschärfe hinzuzufügen. Der Algorithmus verwendet den Durchschnittswert von 5 × 5 um das interessierende Pixel als dieses Pixel.

Beschreibung in OpenCV

Ich werde hier schnell mit OpenCV schreiben.

def run_opencv():
    src = cv2.imread('../../image/twittan/twittan.jpg')
    dst = src.copy()

    roi_x = 100
    roi_y = 100
    roi_w = 150
    roi_h = 200

    dst[roi_y:roi_y + roi_h, roi_x:roi_x + roi_w] = cv2.blur(src[roi_y:roi_y + roi_h, roi_x:roi_x + roi_w], (5, 5),
                                                             (-1, -1))
    print("image size:width = %d, height = %d" % (dst.shape[1], dst.shape[0]))

    cv2.imwrite('twi_blur_cv.jpg', dst)

Bild eingeben

twi.jpg

Ausgabebild

Es gibt eine leichte Unschärfe im Gesicht. twi_blur_cv.jpg

Beschreibung in MyHDL

Dateiorganisation

Dieses Mal verwende ich 5 Dateien. --smooth.py Dies ist das gesamte TOP einschließlich der OpenCV-Verarbeitung. Führen Sie Sim mit python smoothy.py aus. --myhdl_top.py Dies ist die TOP der MyHDL-Umgebung. Beinhaltet Clk und Reset. --smooth_hdl.py RTL wird aufgelistet. --mem.py MyHDL-Simulationsspeichermodell. --Reg_driver.py Setzt das Register.

Prüfstandseite

Es ist eine Beschreibung auf der Prüfstandseite.

CLK, Zurücksetzen usw.

Weggelassen, da es fast das gleiche wie die Probe ist

Registrieren Sie die Einstellungen

Da das Zurücksetzen der positiven Logik nur 1 clk erfolgt, warten wir darauf, dass das Register gesetzt wird. Setzen Sie danach das Startregister für 1clk auf 1 und starten Sie die Verarbeitung, warten Sie, bis das Endregister 1 wird, und beenden Sie die Verarbeitung. Rendite clk.posedge entspricht Warteposition (clk);

reg_driver.py


# -*- coding: utf-8 -*-
__author__ = 'natu'
from myhdl import *

def reg_driver_top(
        clk, reset,
        reg_start, reg_end,
        reg_width, reg_height,
        reg_roi_x, reg_roi_y, reg_roi_h, reg_roi_w
        ):

    @instance
    def regDriver():
        while reset == 0:
            yield clk.posedge
        while reset == 1:
            yield clk.posedge

        reg_width.next = 358
        reg_height.next = 557
        reg_roi_x.next = 100
        reg_roi_y.next = 100
        reg_roi_h.next = 200
        reg_roi_w.next = 150
        yield clk.posedge

        reg_start.next = 1
        yield clk.posedge
        reg_start.next = 0
        yield clk.posedge

        while reg_end == 0:
            yield clk.posedge

        print("end == 1")
        yield clk.posedge

    return regDriver

Erinnerung

Hier konnte die Leistungsfähigkeit von Python demonstriert werden. Sie können OpenCVs Imread verwenden, um eine JPEG-Datei direkt zu öffnen und für Sim zu verwenden. Sie müssen Hex nicht ausgeben und readmemh verwenden. Die Ausgabe kann mit OpenCV auch direkt in ein Bild konvertiert werden.

Die Leseseite aktualisiert read_r, read_g und read_b, wenn sich radr in der Kombinationsschaltung ändert, und die Schreibseite schreibt in den Speicher, wenn wen in der clk-Synchronisation 1 ist.

mem.py


# -*- coding: utf-8 -*-
__author__ = 'natu'
from myhdl import *
import numpy
import cv2

dst = None

def mem_top(
        clk, reset,
        read_r, read_g, read_b, radr,
        write_r, write_g, write_b, wadr, wen):
    global dst

    src = cv2.imread('../../image/twittan/twittan.jpg')
    dst = numpy.zeros(src.shape)

    @always_comb
    def mem_read():
        x, y = adr_dec(radr)
        read_r.next = clop_8bit(src[y][x][0])
        read_g.next = clop_8bit(src[y][x][1])
        read_b.next = clop_8bit(src[y][x][2])


    @instance
    def mem_write():
        while True:
            if wen == 1:
                x, y = adr_dec(wadr)
                dst[y][x][0] = write_r
                dst[y][x][1] = write_g
                dst[y][x][2] = write_b
            yield clk.posedge

    return mem_read, mem_write

def write_image():
    cv2.imwrite('twi_blur_rtl.jpg', dst)

def adr_dec(adr):
    width = dst.shape[1]
    x = int(adr) % width
    y = int(adr) / width
    return x, y

def clop_8bit(x):
    if x >= 255:
        return 255

    return int(x)

RTL-Seite

Da sich die Zustandsmaschine in der Stichprobe befand, habe ich sie vorerst eingefügt, aber es ist keine sehr wichtige Bewegung. Es ist praktisch, x und y verarbeiten zu können.

Mit dieser Doppelschleife erhalten wir 5x5 um das interessierende Pixel.

      for ry in range(-2,3):
          for rx in range(-2,3):

Die Werte werden zu sum_r, sum_g und sum_b addiert und der Durchschnittswert wird bei // 25 berechnet. Es wäre sehr praktisch, wenn Sie es mit genau diesem synthetisieren könnten.

Unten alle Quellen

smooth_hdl.py


# -*- coding: utf-8 -*-
__author__ = 'natu'
from myhdl import *

t_State = enum('IDLE', 'RUNNING')

def smoother_top(
        clk, reset,
        rin, gin, bin, radr,
        rout, gout, bout, wadr, wen,
        reg_start, reg_end,
        reg_width, reg_height,
        reg_roi_x, reg_roi_y, reg_roi_h, reg_roi_w
    ):

    state = Signal(t_State.IDLE)

    @instance
    def main_proc():
        while 1:
            if state == t_State.RUNNING:
                for y in range(reg_height):
                    print("y = %d" % y)
                    for x in range(reg_width):
                        if reg_roi_x <= x and x < reg_roi_x + reg_roi_w and reg_roi_y <= y and y < reg_roi_y + reg_roi_h:
                            # ROI
                            sum_r = 0
                            sum_g = 0
                            sum_b = 0
                            for ry in range(-2,3):
                                for rx in range(-2,3):
                                    radr.next = adr(x + rx, y + ry)
                                    yield  clk.posedge
                                    sum_r = sum_r + rin
                                    sum_g = sum_g + gin
                                    sum_b = sum_b + bin
                                    yield  clk.posedge
                            wadr.next = adr(x, y)
                            rout.next = sum_r // 25
                            gout.next = sum_g // 25
                            bout.next = sum_b // 25
                            wen.next = 1
                            yield  clk.posedge
                            wen.next = 0
                        else:
                            radr.next = adr(x, y)
                            yield  clk.posedge
                            wadr.next = adr(x, y)
                            rout.next = rin
                            gout.next = gin
                            bout.next = bin
                            wen.next = 1
                            yield  clk.posedge
                            wen.next = 0
                reg_end.next = 1
                yield  clk.posedge

            yield  clk.posedge


    def adr(x, y):
        return y * reg_width + x

    @always_seq(clk.posedge, reset=reset)
    def fsm():
        if state == t_State.IDLE:
            if reg_start == 1:
                state.next = t_State.RUNNING
        elif state == t_State.RUNNING:
            if reg_end == 1:
                state.next = t_State.IDLE
        else:
            raise ValueError("Undefined state")
            
    return fsm, main_proc

Verarbeitungsergebnis

Ausgabebild von MyHDL

Es ist fast das gleiche wie das Ergebnis von OpenCV.

twi_blur_rtl.jpg

VCD-Ausgabe

Da vcd auch ausgegeben werden kann, können Sie die Wellenform mit gtkwave überprüfen. Es funktioniert wie erwartet. gtkwave.png

Umstellung auf Verilog

Konvertierungsmethode

Die Konvertierung in Verilog ist auch eine einmalige Konvertierung mit der Funktion toVerilog. Während 1: OK ist, während True nutzlos ist und es einige subtile Barrieren gab, konnte ich mit dieser Beschreibung Verilog.

    toVerilog(smoother_top,
        clk, reset,
        rin, gin, bin, radr,
        rout, gout, bout, wadr, wen,
        reg_start, reg_end,
        reg_width, reg_height,
        reg_roi_x, reg_roi_y, reg_roi_h, reg_roi_w
    )

Konvertierungsergebnis

Das ist aufregend.

// File: smoother_top.v
// Generated by MyHDL 0.9.dev0
// Date: Tue May 19 14:30:05 2015


`timescale 1ns/10ps

module smoother_top (
    clk,
    reset,
    rin,
    gin,
    bin,
    radr,
    rout,
    gout,
    bout,
    wadr,
    wen,
    reg_start,
    reg_end,
    reg_width,
    reg_height,
    reg_roi_x,
    reg_roi_y,
    reg_roi_h,
    reg_roi_w
);


input clk;
input reset;
input [7:0] rin;
input [7:0] gin;
input [7:0] bin;
output [19:0] radr;
reg [19:0] radr;
output [7:0] rout;
reg [7:0] rout;
output [7:0] gout;
reg [7:0] gout;
output [7:0] bout;
reg [7:0] bout;
output [19:0] wadr;
reg [19:0] wadr;
output wen;
reg wen;
input reg_start;
output reg_end;
reg reg_end;
input [9:0] reg_width;
input [9:0] reg_height;
input [9:0] reg_roi_x;
input [9:0] reg_roi_y;
input [9:0] reg_roi_h;
input [9:0] reg_roi_w;

reg [0:0] state;




function integer MYHDL13_adr;
    input x;
    integer x;
    input y;
    integer y;
begin: MYHDL17_RETURN
    MYHDL13_adr = ((y * $signed({1'b0, reg_width})) + x);
    disable MYHDL17_RETURN;
end
endfunction

function integer MYHDL14_adr;
    input x;
    integer x;
    input y;
    integer y;
begin: MYHDL18_RETURN
    MYHDL14_adr = ((y * $signed({1'b0, reg_width})) + x);
    disable MYHDL18_RETURN;
end
endfunction

function integer MYHDL15_adr;
    input x;
    integer x;
    input y;
    integer y;
begin: MYHDL19_RETURN
    MYHDL15_adr = ((y * $signed({1'b0, reg_width})) + x);
    disable MYHDL19_RETURN;
end
endfunction

function integer MYHDL16_adr;
    input x;
    integer x;
    input y;
    integer y;
begin: MYHDL20_RETURN
    MYHDL16_adr = ((y * $signed({1'b0, reg_width})) + x);
    disable MYHDL20_RETURN;
end
endfunction


always @(posedge clk, posedge reset) begin: SMOOTHER_TOP_FSM
    if (reset == 1) begin
        state <= 1'b0;
    end
    else begin
        case (state)
            1'b0: begin
                if ((reg_start == 1)) begin
                    state <= 1'b1;
                end
            end
            1'b1: begin
                if ((reg_end == 1)) begin
                    state <= 1'b0;
                end
            end
            default: begin
                $finish;
            end
        endcase
    end
end


initial begin: SMOOTHER_TOP_MAIN_PROC
    integer sum_b;
    integer rx;
    integer ry;
    integer sum_g;
    integer y;
    integer x;
    integer sum_r;
    while (1) begin
        if ((state == 1'b1)) begin
            for (y=0; y<reg_height; y=y+1) begin
                $write("y = ");
                $write("%0d", y);
                $write("\n");
                for (x=0; x<reg_width; x=x+1) begin
                    if ((($signed({1'b0, reg_roi_x}) <= x) && (x < (reg_roi_x + reg_roi_w)) && ($signed({1'b0, reg_roi_y}) <= y) && (y < (reg_roi_y + reg_roi_h)))) begin
                        sum_r = 0;
                        sum_g = 0;
                        sum_b = 0;
                        for (ry=(-2); ry<3; ry=ry+1) begin
                            for (rx=(-2); rx<3; rx=rx+1) begin
                                radr <= MYHDL13_adr((x + rx), (y + ry));
                                @(posedge clk);
                                sum_r = (sum_r + rin);
                                sum_g = (sum_g + gin);
                                sum_b = (sum_b + bin);
                                @(posedge clk);
                            end
                        end
                        wadr <= MYHDL14_adr(x, y);
                        rout <= (sum_r / 25);
                        gout <= (sum_g / 25);
                        bout <= (sum_b / 25);
                        wen <= 1;
                        @(posedge clk);
                        wen <= 0;
                    end
                    else begin
                        radr <= MYHDL15_adr(x, y);
                        @(posedge clk);
                        wadr <= MYHDL16_adr(x, y);
                        rout <= rin;
                        gout <= gin;
                        bout <= bin;
                        wen <= 1;
                        @(posedge clk);
                        wen <= 0;
                    end
                end
            end
            reg_end <= 1;
            @(posedge clk);
        end
        @(posedge clk);
    end
end

endmodule

initial begin: SMOOTHER_TOP_MAIN_PROC、、、

(Tsu д ⊂) Gojigoshi → (; ゚ Д ゚)…! ??

People People People People People People > initial begin: <  ̄Y^Y^Y^Y^Y^Y^ ̄

Ich kann nicht synthetisieren! Nicht gut> <

Impressionen

Guter Platz

Ich wollte Behauptungen und Berichterstattung ausprobieren, war aber so überwältigt, dass ich die von mir erstellte Schaltung nicht synthetisieren konnte, also konnte ich nicht so weit gehen.

Wo es nicht funktioniert hat

――Es ist sehr schwierig, eine sich bewegende Schaltung zu schreiben. Es ist nicht intuitiv, eine Funktion zurückzugeben, die das Verhalten der Schaltung beschreibt. Schwer zu debuggen.

    @always_seq(clk.posedge, reset=reset)
    def fsm():
        if state == t_State.IDLE:
            if reg_start == 1:
                state.next = t_State.RUNNING
        elif state == t_State.RUNNING:
            if reg_end == 1:
                state.next = t_State.IDLE
        else:
            raise ValueError("Undefined state")

Die Beschreibung, die synthetisiert werden kann, ist dieses Muster, und Sie müssen einen Generator schreiben, der keine Ausbeute in der Mitte enthält. Mit anderen Worten, es ist dasselbe wie Verilog-HDL. Es ist nur eine Modellierungssprache.

Recommended Posts

Bildverarbeitung mit MyHDL
Bildverarbeitung mit Python
Bildverarbeitung mit PIL
Bildverarbeitung mit Python (Teil 2)
Bildverarbeitung mit PIL (Pillow)
Bildverarbeitung mit Python (Teil 1)
Bildverarbeitung mit Python (3)
[Python] Bildverarbeitung mit Scicit-Image
Grundlagen der Echtzeit-Bildverarbeitung mit opencv
Die Bildverarbeitung mit Python 100 klopft an die Binärisierung Nr. 3
100 Bildverarbeitung mit Python Knock # 2 Graustufen
[Bildverarbeitung] Posterisierung
Python-Bildverarbeitung
Bildverarbeitung 100 Schläge ①
Grundlagen der binärisierten Bildverarbeitung durch Python
Bildverarbeitung mit Python 100 Knock # 10 Medianfilter
Erstellen Sie mit PySimpleGUI einen Bildverarbeitungs-Viewer
100 Bildverarbeitung mit Python Knock # 8 Max Pooling
Bildverarbeitung mit Python & OpenCV [Tonkurve]
Bildverarbeitung mit Python 100 Knock # 12 Bewegungsfilter
Zeichnen mit Matrix-Reinventor von Python Image Processing-
Verarbeiten Sie Bilder in Python ganz einfach mit Pillow
Die Bildverarbeitung mit Python 100 führt zu einem durchschnittlichen Pooling von # 7
Leichte Bildverarbeitung mit Python x OpenCV
Bildverarbeitung mit Lambda + OpenCV (graue Bilderzeugung)
Bildverarbeitung mit Python 100 Knock # 9 Gauß-Filter
XavierNX beschleunigt die OpenCV-Bildverarbeitung mit GPU (CUDA)
Datensätze mit Pandas verarbeiten (1)
Datensätze mit Pandas verarbeiten (2)
Bilderkennung mit Keras
Bildverarbeitung von Grund auf mit Python (5) Fourier-Transformation
Erste Python-Bildverarbeitung
Lesen Sie die digitale Bildverarbeitung
Bildverarbeitung von Grund auf mit Python (4) Konturextraktion
Bildverarbeitung mit Python Environment Setup für Windows
Parallelverarbeitung mit Mehrfachverarbeitung
Hinweise zur HDR- und RAW-Bildverarbeitung mit Python
Bild herunterladen mit Flickr API
100 Sprachverarbeitungsklopfen mit Python 2015
opencv-python Einführung in die Bildverarbeitung
Lesen Sie die Bildkoordinaten mit Python-matplotlib
Parallelverarbeitung mit lokalen Funktionen
"Apple-Verarbeitung" mit OpenCV3 + Python3
Bildbearbeitung mit Python OpenCV
Akustische Signalverarbeitung mit Python (2)
Digitale Bildverarbeitung (räumliche Filterung)
100 Schläge bei der Bildverarbeitung !! (011-020) Frühes Spiel
Hochladen und Anpassen von Bildern mit django-ckeditor
Sortieren von Bilddateien mit Python (2)
Sortieren von Bilddateien mit Python (3)
100 Klopfen bei der Bildverarbeitung !! (001 - 010) Vorsichtig und vorsichtig
Parallele Verarbeitung mit Parallel von Scikit-Learn
Erstellen Sie den Image Viewer mit Tkinter
Tweet mit Bild in Python
Bilddateien mit Python sortieren
Bildverarbeitung mit Python (Pillow)
Bildverarbeitungssammlung in Python