「完结撒花」使用intel realsense D435i深度相机获取信息,DOBOT MG400机械手实现动态实时抓取,并做了个GUI界面(python实现)

GUI界面如下,丑是丑了点,但很好用,嘿嘿。 

GUI部分

 

1.GUI界面可以实现的功能

  • 暂停・继续相机画面
  • 显示彩色RGB图像・深度图像・开运算结果图・进行图像处理后的图片(右侧)
  • 调节opencv轮廓查找框选面积范围
  • 调节图像区域
  • 给dobot机械手使能
  • 机械手的移动,复位,夹爪开关,z轴上下移动,自动运行和停止

2.GUI部分代码

①布局

1.菜单栏f1

"""
菜单栏 f1
"""
f1 = Frame(root)
info_width = 1280
info_height = 30
canvas_menu = Canvas(f1, width=info_width, height=info_height)
canvas_menu.pack(side=LEFT, padx=1, pady=1)
f1.pack()

虽然目前菜单栏还没东西也没功能,但留了一条备用

2.功能区域f2

"""
功能区域 f2
"""
f2 = Frame(root)
# info_width = 1280
# info_height = 434
frame_fun = Frame(f2, width=880, height=324)
frame_screenshot = Frame(f2, width=400, height=324)
frame_fun.pack(side=LEFT, padx=1, pady=1)
frame_screenshot.pack(side=LEFT, padx=1, pady=1)
f2.pack()

按钮们

btn_pause = Button(frame_fun, text="CAMERA PAUSE", width=10, height=1, command=pause_camera)
btn_pause.place(x=10, y=10)
btn_dobot_pause = Button(frame_fun, text="ロボット起動", width=10, height=1, command=dobot_enable)
btn_dobot_pause.place(x=110, y=10)
btn_dobot_move = Button(frame_fun, text="目標位置へ移動", width=10, height=1, command=dobot_move)
btn_dobot_move.place(x=210, y=10)
btn_dobot_move_home = Button(frame_fun, text="原点", width=10, height=1, command=dobot_move_home)
btn_dobot_move_home.place(x=310, y=10)
btn_dobot_nail_on = Button(frame_fun, text="チャック開", width=10, height=1, command=dobot_nail_on)
btn_dobot_nail_on.place(x=410, y=10)
btn_dobot_nail_off = Button(frame_fun, text="チャック閉", width=10, height=1, command=dobot_nail_off)
btn_dobot_nail_off.place(x=510, y=10)
btn_dobot_move_down = Button(frame_fun, text="down", width=10, height=1, command=dobot_move_down)
btn_dobot_move_down.place(x=610, y=10)
btn_dobot_move_up = Button(frame_fun, text="up", width=10, height=1, command=dobot_move_up)
btn_dobot_move_up.place(x=710, y=10)
btn_dobot_automove = Button(frame_fun, text="自動運転", width=10, height=1, command=dobot_automove)
btn_dobot_automove.place(x=610, y=60)
btn_dobot_automove_stop = Button(frame_fun, text="自動運転停止", width=10, height=1, command=dobot_automove_stop)
btn_dobot_automove_stop.place(x=710, y=60)

检出面积滑块们

# 检出面积滑块们
var_min = IntVar()
scl_area_min = Scale(frame_fun, orient=HORIZONTAL, length=200, width=10, from_=1000, to=5000, label='最小検出サイズ (1500)', tickinterval=1, resolution=50, variable=var_min)
area_min = 1500
var_min.set(1500)
scl_area_min.bind('<ButtonRelease-1>', get_var_min)
scl_area_min.place(x=10, y=60)

var_max = IntVar()
scl_area_max = Scale(frame_fun, orient=HORIZONTAL, length=200, width=10, from_=1000, to=5000, label='最大検出サイズ (5000)', tickinterval=1, resolution=50, variable=var_max)
area_max = 5000
var_max.set(5000)
scl_area_max.bind('<ButtonRelease-1>', get_var_max)
scl_area_max.place(x=230, y=60)

裁剪面积滑块们

# 裁剪面积滑块们
var_sliced_left = IntVar()
scl_sliced_left = Scale(frame_fun, orient=HORIZONTAL, length=200, width=10, from_=0, to=640, label='sliced_left (500)', tickinterval=1, resolution=10, variable=var_sliced_left)
sliced_left = 540
var_sliced_left.set(540)
scl_sliced_left.bind('<ButtonRelease-1>', get_sliced_left)
scl_sliced_left.place(x=10, y=140)

var_sliced_right = IntVar()
scl_sliced_right = Scale(frame_fun, orient=HORIZONTAL, length=200, width=10, from_=640, to=1280, label='sliced_right (930)', tickinterval=1, resolution=10, variable=var_sliced_right)
sliced_right = 960
var_sliced_right.set(960)
scl_sliced_right.bind('<ButtonRelease-1>', get_sliced_right)
scl_sliced_right.place(x=230, y=140)

var_sliced_up = IntVar()
scl_sliced_up = Scale(frame_fun, orient=HORIZONTAL, length=200, width=10, from_=0, to=360, label='sliced_up (150)', tickinterval=1, resolution=10, variable=var_sliced_up)
sliced_up = 220
var_sliced_up.set(220)
scl_sliced_up.bind('<ButtonRelease-1>', get_sliced_up)
scl_sliced_up.place(x=450, y=140)

var_sliced_down = IntVar()
scl_sliced_down = Scale(frame_fun, orient=HORIZONTAL, length=200, width=10, from_=360, to=720, label='sliced_down (570)', tickinterval=1, resolution=10, variable=var_sliced_down)
sliced_down = 570
var_sliced_down.set(570)
scl_sliced_down.bind('<ButtonRelease-1>', get_sliced_down)
scl_sliced_down.place(x=670, y=140)

log日志部分

# log日志
message_dobot = Text(frame_fun, height=1, cursor='arrow', width=25)
message_dobot.insert("insert", "wait for dobot")
message_dobot.config(fg='red')
message_dobot.place(x=10, y=280)
message_log = Text(frame_fun, height=1, cursor='arrow', width=25)
message_log.place(x=10, y=300)

3.下方相机画面部分

"""
相机区域 f3
"""
f3 = Frame(root)
frame_width = 427
frame_height = 366
rgb_frame = Frame(f3, width=frame_width, height=frame_height)
depth_frame = Frame(f3, width=frame_width, height=frame_height)
opening_frame = Frame(f3, width=frame_width, height=frame_height)
rgb_frame.pack(side=LEFT, padx=1, pady=1)
depth_frame.pack(side=LEFT, padx=1, pady=1)
opening_frame.pack(side=LEFT, padx=1, pady=1)
f3.pack()

rgb_info = Label(rgb_frame, text="LIVE", font=("游明朝", 10))
rgb_info.place(x=5, y=0)
canvas_rgb = Canvas(rgb_frame)
canvas_rgb.place(x=25, y=50)
depth_info = Label(depth_frame, text="DEPTH", font=("游明朝", 10))
depth_info.place(x=5, y=0)
canvas_depth = Canvas(depth_frame)
canvas_depth.place(x=25, y=50)
opening_info = Label(opening_frame, text="OPENING", font=("游明朝", 10))
opening_info.place(x=5, y=0)
canvas_opening = Canvas(opening_frame)
canvas_opening.place(x=25, y=50)

②按钮绑定的函数们

  • 暂停・继续画面  def pause_camera():

 这部分比较简单,实现声明一个realsense相机的类,把类里的暂停状态改一下就可以

class State:
    def __init__(self, *args, **kwargs):
        self.WIN_NAME = 'RealSense'
        self.paused = False

state = State()
def pause_camera():
    state.paused ^= True
  • 获取滑块值 以获取左侧裁剪区域值为例 def get_sliced_left(event):
def get_sliced_left(event):
    global sliced_left
    sliced_left = int(var_sliced_left.get())
  •  机器人使能 def dobot_enable():

使用tcp-ip地址连接机器人,创建多线程对象,由于机械臂收到信息会立刻返回,在循环最后面需要向30003发送Sync()指令做一个阻塞,等待前面执行完成再反馈0{}Sync(),否则会出现程序停止机械臂还在运作这样的情况。 

def dobot_enable():
    global lj29999
    global lj30003
    lj29999 = LJ29999("192.168.1.6", 29999)  # 创建实例对象
    lj30003 = LJ30003("192.168.1.6", 30003)
    # # 根据自己处理器自行判断使用线程还是进程
    thread = Thread(target=FK,  # 新建一个线程做数据刷新
                    daemon=True  # 设置新线程为daemon线程
                    )
    thread.start()
    lj29999.send(" EnableRobot()")
    print("机器人使能中...")
    message_dobot.delete(1.0, END)
    message_dobot.insert("insert", "机器人使能中...")
    message_dobot.config(fg='black')
def FK():
    fk30005 = feedback("192.168.1.6", 30005)  # 处理器性能较弱可以使用30005反馈
    while True:
        time.sleep(0.021)  # 略大于反馈时间即可
        fk30005.read()
        # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
        # print((fk30005.basics[1]))  # 打印轴实时位置

③下方视频区域

message_log.delete(1.0, END)
message_log.insert("insert", "live中...")
image_to_arm, arm_to_image = coordinate_transform()
img_color, img_depth, color_intrin, intr_matrix, color_intrin_coeffs, aligned_depth_frame, depth_mapped_image = get_aligned_images()
target_rgb, target_depth, target_opening = camera()
canvas_rgb.create_image(0, 0, anchor='nw', image=target_rgb)
canvas_depth.create_image(0, 0, anchor='nw', image=target_depth)
canvas_opening.create_image(0, 0, anchor='nw', image=target_opening)

root.update()
root.after(1)

视频实现时获取相机各个画面后,创建图片在画布上,实时刷新,已到达视频效果。

完整程序文件改日上传~!

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个简单的撒花动画的 C 代码,使用了 Windows API 实现: ```c #include <windows.h> #define MAX_PARTICLES 1000 typedef struct { float x, y; float vx, vy; int life; COLORREF color; } Particle; Particle particles[MAX_PARTICLES]; void update_particles(int width, int height) { for (int i = 0; i < MAX_PARTICLES; i++) { Particle* p = &particles[i]; if (p->life <= 0) { p->x = (float)(rand() % width); p->y = (float)(rand() % height); p->vx = 2.0f * ((float)rand() / RAND_MAX) - 1.0f; p->vy = 2.0f * ((float)rand() / RAND_MAX) - 1.0f; p->life = 50 + rand() % 50; p->color = RGB(rand() % 256, rand() % 256, rand() % 256); } else { p->x += p->vx; p->y += p->vy; p->vx *= 0.98f; p->vy *= 0.98f; p->life--; } } } void draw_particles(HDC hdc) { for (int i = 0; i < MAX_PARTICLES; i++) { Particle* p = &particles[i]; if (p->life > 0) { HBRUSH brush = CreateSolidBrush(p->color); SelectObject(hdc, brush); Ellipse(hdc, p->x - 5, p->y - 5, p->x + 5, p->y + 5); DeleteObject(brush); } } } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { srand(GetTickCount()); int width = 800; int height = 600; HWND hwnd = CreateWindow("STATIC", "撒花动画", WS_VISIBLE | WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, NULL, NULL, hInstance, NULL); HDC hdc = GetDC(hwnd); while (true) { MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) { return 0; } TranslateMessage(&msg); DispatchMessage(&msg); } update_particles(width, height); RECT rect; GetClientRect(hwnd, &rect); FillRect(hdc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH)); draw_particles(hdc); Sleep(16); } ReleaseDC(hwnd, hdc); DestroyWindow(hwnd); return 0; } ``` 这个程序使用了一个 `Particle` 结构体来表示每个粒子,包含了位置、速度、生命和颜色等信息。在 `update_particles` 函数中,每个粒子会根据当前的位置和速度进行更新,同时减少生命值。如果生命值降低到 0,那么这个粒子就会被重新生成在随机位置,并获得一个新的生命值和颜色。在 `draw_particles` 函数中,每个粒子会被画成一个小圆点。 在主函数中,程序进入一个无限循环,每次循环中都会处理消息队列并调用 `update_particles` 和 `draw_particles` 函数。程序会每秒钟刷新 60 次,因为每次循环中都会调用 `Sleep(16)`,即暂停 16 毫秒,这相当于每秒钟刷新 1000 / 16 = 62.5 次,略微超过了我们的目标。 要编译这个程序,可以使用 Visual Studio 或者 MinGW 等工具,在命令行中输入以下命令: ``` gcc -o sahua.exe sahua.c -lgdi32 ``` 这个命令会将 `sahua.c` 编译成可执行文件 `sahua.exe`,并链接 Windows GDI 库。运行程序后,你就可以看到一个简单的撒花动画了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值