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
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.
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)

Es gibt eine leichte Unschärfe im Gesicht.

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.
Es ist eine Beschreibung auf der Prüfstandseite.
Weggelassen, da es fast das gleiche wie die Probe ist
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
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)
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
Es ist fast das gleiche wie das Ergebnis von OpenCV.

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

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
    )
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> <
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.
――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