In this notebook we will demonstrate a hardware accelerated edge detection filter.
This filter uses the Sobel operator to estimate the gradients of the image in the X and Y directions. The two gradients are then summed displayed onscreen.
For more information on the Sobel operator, consult Wikipedia.
In [1]:
from pynq.drivers.video import HDMI
from pynq import Bitstream_Part
from pynq.board import Register
from pynq import Overlay
Overlay("demo.bit").download()
In [2]:
hdmi_in = HDMI('in')
hdmi_out = HDMI('out', frame_list=hdmi_in.frame_list)
hdmi_out.mode(2)
hdmi_out.start()
hdmi_in.start()
In [3]:
Bitstream_Part("sobel_p.bit").download()
In [4]:
import ipywidgets as widgets
R0 = Register(0)
R1 = Register(1)
R2 = Register(2)
R3 = Register(3)
R4 = Register(4)
R0.write(128)
R1.write(1)
R2.write(0)
R3.write(hdmi_in.frame_width()//2)
R4.write(0)
R0_s = widgets.IntSlider(
value=128,
min=0,
max=255,
step=1,
description='Threshold',
disabled=False,
continuous_update=True,
orientation='vertical',
readout=True,
readout_format='i',
slider_color='red',
width='80px'
)
R1_s = widgets.IntSlider(
value=14,
min=0,
max=15,
step=1,
description='Sensitivity',
disabled=False,
continuous_update=True,
orientation='vertical',
readout=True,
readout_format='i',
slider_color='green',
width='80px'
)
R2_s = widgets.ToggleButton(
value=False,
description='Invert',
disabled=False,
#button_style='', # 'success', 'info', 'warning', 'danger' or ''
tooltip='Invert',
icon='check',
width='120px'
)
R3_s = widgets.IntSlider(
value=hdmi_in.frame_width()//2,
min=0,
max=hdmi_in.frame_width(),
step=1,
description='Window',
disabled=False,
continuous_update=True,
orientation='vertical',
readout=True,
readout_format='i',
slider_color='yellow',
width='80px'
)
R4_s = widgets.ToggleButton(
value=False,
description='Rotoscope',
disabled=False,
#button_style='', # 'success', 'info', 'warning', 'danger' or ''
tooltip='Invert',
icon='check',
width='120px'
)
def update_r0(*args):
R0.write(R0_s.value)
def update_r1(*args):
R1.write(15 - R1_s.value)
def update_r2(*args):
R2.write(int(R2_s.value))
def update_r3(*args):
R3.write(R3_s.value)
def update_r4(*args):
R4.write(int(R4_s.value))
R0_s.observe(update_r0, 'value')
R1_s.observe(update_r1, 'value')
R2_s.observe(update_r2, 'value')
R3_s.observe(update_r3, 'value')
R4_s.observe(update_r4, 'value')
widgets.VBox([ widgets.HBox( [R0_s, R1_s, R3_s]), widgets.HBox([R2_s, R4_s]) ])
Feel free to play with the sliders and buttons above. For reference, their functions are as follows:
Have fun!
In [5]:
hdmi_out.stop()
hdmi_in.stop()
del hdmi_out
del hdmi_in