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