python+pygame+opencv+gpt实现虚拟数字人直播(一)

AI技术突飞猛进,不断的改变着人们的工作和生活。数字人直播作为新兴形式,必将成为未来趋势,具有巨大的、广阔的、惊人的市场前景。它将不断融合创新技术和跨界合作,提供更具个性化和多样化的互动体验,成为未来的一种趋势。

前言

马斯克称:“人工智能将在我们所看到的人类进化和文明的未来发挥非常深远的作用。未来我们会拥有大量的机器人,到时候,全球的生产效率将会提高到令人难以置信的水平。”,机器人可以完成行走、上下楼、下蹲、拿取物品等动作,也已具备了保护自身和周围人安全的能力,未来还可以做饭、修剪草坪、帮助照看老人,或在工厂里面替代人类从事枯燥和有危险的工作。

不久前的世界互联网大会数字文明尼山对话上,阿里巴巴集团董事会主席兼首席执行官、阿里云智能集团董事长兼首席执行官张勇也表示,AI的发展将会带来更多的就业机会。站在智能化新时代,所有行业都值得基于人工智能技术重做一遍。‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

只不过效率提升的同时,迎面而来的也是人类与AI的近距离博弈。在AIGC时代影响下,人们已经可以用非常低的成本用上ChatGPT、StableDiffusion以及 Mid-journey等AI产品。很多岗位面临着替代的风险,文字工作者、画师、广告设计,甚至是带货主播等。

虽然网上有些公司已实现了虚拟数字人技术,但收费都不菲。这里使用python尝试玩一下虚拟数字人直播,作为有趣的探索和低成本的实现。如果探索可行,可以自己搞一个虚拟数字人直播玩玩儿,挂在自己的抖音上二十四小时在线,岂不美哉!

python实现的虚拟数字人直播

利用AI技术除了虚拟数字人直播外,AR 导购、虚拟试穿、虚拟主播、3D 样板间等新玩法的出现,实现了直播电商在观看体验、直播效率、商业价值上的全面提速。在不同的应用场景下,人工智能和真人主播可以互补互助,为消费者提供多元的观看体验,例如人工智能的语言处理可以更快速地理解和回应用户的问题和需求,而真人主播则可以在直播过程中与用户进行情感上的交流互动,拉近直播间与用户间的距离。 

数字人直播的惊天优势

利用数字人直播新媒体平台,可以让数字人直播24小时随时开播、自动带货。

数字人直播帮助本地生活商家实现爆破式增长。

数字人直播深度还原真人形象告别出镜难题。

数字人直播文案一键输入3S出片短视频产量指数级增长。

数字人直播可利用GPT互动功能,GPT直播生成内容自动互动,回复不重样。

利用文心一言、讯飞星火或chatGPT等人工智能语音交互技术,让数字人直播真正的走向实战,成为可能。

Python实现的技术方案

Python可以用于实现虚拟数字人,使其具备动画和说话的能力。

一个可行的技术方案探索:

1. 人物建模和动画:使用计算机图形学技术,可以使用Python库如Pygame、Pyglet、OpenGL等创建人物的3D模型,并为其添加动画效果。可以使用3D建模软件(如Blender)创建人物模型,并使用Python编写脚本来控制模型的动画。

2. 语音合成:使用Python库如pyttsx3、gTTS等,可以将文本转换为语音。这些库提供了API,可以将文本输入,并生成相应的语音输出。

3. 对话系统:使用Python的自然语言处理(NLP)和机器学习技术,可以构建一个对话系统,使虚拟数字人能够理解和生成自然语言的对话。可以使用NLP库如NLTK、SpaCy等来处理自然语言,并使用机器学习库如TensorFlow、PyTorch等来训练对话模型。

4. 用户界面:使用Python的GUI库如Tkinter、PyQt等,可以创建一个用户界面,使用户能够与虚拟数字人进行交互。可以在界面上显示虚拟人物的动画,并提供文本框或语音输入来与其进行对话。

方案介绍

1. 人物建模和动画: 使用计算机图形学技术创建人物的2D或3D模型,可以使用Blender等建模软件进行建模。将人物的不同面部表情和动作设计为不同的图像帧或动画序列。或自己录制,或从网上剪辑需要的人物视频和图片素材。

2. 精灵类的使用: - 创建一个继承自pygame.sprite.Sprite的虚拟数字人类。  在虚拟数字人类中,使用pygame.image.load()加载人物的图像帧或动画序列。  使用pygame.Surface.blit()方法在屏幕上绘制当前的图像帧。

3. 面部表情和动作切换: - 在虚拟数字人类中,定义方法来切换人物的面部表情和动作。 - 使用pygame.time.set_timer()来定时触发表情和动作的切换,创建一个定时器事件。

4. 发音和语音合成: - 使用Python的语音合成库,如pyttsx3、gTTS等,或百度、科大讯飞等的语音接口,将文本转换为语音。 - 定义方法来触发虚拟数字人的发音,根据需要播放相应的语音。

5. 用户交互: - 创建一个pygame窗口,用于显示虚拟数字人和与用户进行交互。  使用pygame.event.get()监听用户的事件,例如键盘输入或鼠标点击。 - 根据用户的输入,调用相应的方法来切换人物的面部表情、动作和发音。让用户的聊天内容文字发给GPT,形成内容并通过文字转语音回复给用户,同时配合不同的动作和表情。

环境依赖

1.下载安装python3,Python 官网:Welcome to Python.org

2.安装依赖的模块: pygame,pygame-pgu,opencv,rembg

pip install rembg -i https://pypi.tuna.tsinghua.edu.cn/simple/
pip install opencv-python

3.替换pip安装的资源镜像(否则下载模块很慢)

pip  config set  global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
4.图片和语音素材

5.讯飞离线语音合成工具

素材制作

可以使用3D建模软件(如Blender)创建人物模型,这里简单起见,部分素材从网上搜索下载到的,仅用于学习研究目的,如有侵权请联系我。

Rembg是一款图片背景去除工具. 这里我先简单介绍下它的特点。

  • 开源、免费

  • 基于 Python 开发

  • 后台引擎是用于显著对象检测的深度网络架构 U²-Net(后文有简单介绍)

  • 安装简单

背景图片

人物图片

 

代码实现

加载图片背景

#背景实现
class BackGround(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load('./image/background.png').convert()
        self.image = pygame.transform.scale(self.image, (WIDTH, HEIGHT))
        self.rect = self.image.get_rect()
        self.ready_to_move = 0
        self.index = 0

    def update(self, *args):
        pass

提取视频图片帧

从一段视频中提取视频图片帧。

在pygame中,Sprite精灵通常使用图像来实现动画效果。尽管pygame本身不直接支持加载和播放mp4格式的视频文件,但可以通过一些额外的库来实现加载和播放视频的功能。 一个常用的库是 moviepy ,它是一个用于视频编辑和处理的Python库。可以使用 moviepy 库将mp4视频文件转换为一系列图像帧,然后使用这些图像帧来创建Sprite精灵动画。

下面是一个示例:

import pygame
from moviepy.editor import VideoFileClip

# 加载mp4视频并提取图像帧
video = VideoFileClip("animation.mp4")
frames = [pygame.image.fromstring(video.get_frame(t), video.size, "RGB") for t in range(0, int(video.duration*video.fps))]

# 初始化pygame
pygame.init()
screen = pygame.display.set_mode(video.size)

# 创建Sprite精灵对象
class AnimatedSprite(pygame.sprite.Sprite):
    def __init__(self, frames):
        super().__init__()
        self.frames = frames
        self.current_frame = 0
        self.image = self.frames[self.current_frame]
        self.rect = self.image.get_rect()

    def update(self):
        self.current_frame = (self.current_frame + 1) % len(self.frames)
        self.image = self.frames[self.current_frame]

# 创建精灵对象并添加到精灵组
sprite = AnimatedSprite(frames)
sprite_group = pygame.sprite.Group(sprite)

clock = pygame.time.Clock()

# 游戏循环
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    sprite_group.update()

    screen.fill((0, 0, 0))
    sprite_group.draw(screen)
    pygame.display.flip()
    clock.tick(30)

pygame.quit()

提取视频帧并保存为png格式的图片,同时去除背景:

# 加油动作手势
    def comeOn(self):
        # 加载mp4视频并提取图像帧
        video = VideoFileClip("./mp4/1.mp4")
        # Get the video dimensions
        video_width, video_height = video.size
        # 创建一个pygame surface
        #surface = pygame.Surface((video_width, video_height))
        #frames = [pygame.image.fromstring(np.array(video.get_frame(t)).tobytes(), video.size, "RGB") for t in range(0, int(video.duration*video.fps))]
        # Create a pygame surface with alpha channel
        surface = pygame.Surface((video_width, video_height), pygame.SRCALPHA)

        # Convert each frame of the video to an image with transparency
        frames = []
        for t in range(int(video.duration * video.fps)):
            frame = video.get_frame(t)
            pygame.surfarray.blit_array(surface, frame.swapaxes(0, 1))
            # 将帧保存为PNG图像
            image = pygame.surfarray.array3d(surface).swapaxes(0, 1)
            image = np.uint8(image)
            pil_image = Image.fromarray(image)
            #去除图片的白色背景
            image = remove(pil_image)
            #保存png图片
            image.save(f"framet_{t}.png")
            # Convert PIL Image to pygame surface
            pygame_image = pygame.image.fromstring(image.tobytes(), image.size, image.mode).convert_alpha()
            
            frames.append(pygame_image)
        self.frames = frames
        print("frames count:"+str(len(self.frames)))
        self.current_frame = 0
        self.image = self.frames[self.current_frame]
        self.state = "comeOn"
        self.start = time.time()

也可以使用opencv提取mp4视频中的图片帧,代码示例:

import cv2

# 打开视频文件
video = cv2.VideoCapture('2.mp4')

# 设置帧计数器
frame_count = 0

while True:
    # 读取视频的每一帧
    ret, frame = video.read()

    # 如果没有读到帧,说明视频已经结束
    if not ret:
        break

    # 保存帧图片
    cv2.imwrite(f'output/frame_{frame_count}.jpg', frame)

    # 帧计数器自增
    frame_count += 1

# 释放视频对象
video.release()

实现过程

# -*- coding: utf-8 -*-
# @Author : yangyongzhen
# @Email : 534117529@qq.com
# @File : mqttclienttool.py
# @Project : study
import pygame
from moviepy.editor import VideoFileClip
import numpy as np
import time
from PIL import Image
from rembg import remove
import cv2

# 常量 屏幕大小
WIDTH, HEIGHT = 500, 900
print(cv2.__version__)
# 初始化操作
pygame.init()
pygame.mixer.init()
# 创建窗口
screen = pygame.display.set_mode((WIDTH, HEIGHT))

# 设置窗口标题
pygame.display.set_caption('虚拟数字人--关注作者:blog.csdn.net/qq8864')

# 添加背景音乐
pygame.mixer.music.load('./sound/bgLoop.wav')
pygame.mixer.music.set_volume(0.5)  # 音量
#pygame.mixer.music.play(-1, 0)
# 添加系统时钟
FPS = 30
clock = pygame.time.Clock()
# 创建用户自定义事件,每隔1000毫秒触发一次事件
USER_EVENT = pygame.USEREVENT
pygame.time.set_timer(USER_EVENT, 1000)

# 加载字体文件
font_path = "./font/SIMYOU.ttf"  # 替换为你的字体文件路径
font_size = 24
font = pygame.font.Font(font_path, font_size)
       
# ========虚拟数字人主角==========
# class Hero(pygame.sprite.Sprite)
# class BackGround(pygame.sprite.Sprite)
# 虚拟人主角 (静默状态保持微笑和3秒眨一次眼睛)
class VirtualMan(pygame.sprite.Sprite):
    def __init__(self, speed):
        super().__init__()
        self.image = pygame.image.load('./image/man.png')
        self.image_index = 0
        self.readt_to_change = 0
        self.rect = self.image.get_rect()
        self.rect.width *= 0.5
        self.rect.height *= 0.5
        self.image = pygame.transform.scale(self.image, (self.rect.width, self.rect.height))
        self.rect.x, self.rect.y = 0, 100
        self.speed = speed
        self.frames = None
        self.current_frame = 0
        self.state = "idle"

    def update(self, *args):
        #这里用上下左右、空格几个按键来测试虚拟数字人的不同动作
        keys = pygame.key.get_pressed()
        if keys[pygame.K_UP]:
            #加油动作手势
            self.comeOn()
        if keys[pygame.K_DOWN]:
            #欢迎动作手势
            self.welcome()
        if keys[pygame.K_LEFT]:
            #说话动作和表情
            self.say()
        if keys[pygame.K_RIGHT]:
            #停下来
            self.stop()
        if keys[pygame.K_SPACE]:
            #欢迎动作手势
            self.goodbye()
            
        if self.state == "comeOn":   
               self.current_frame = (self.current_frame + 1) % len(self.frames)
               self.image = pygame.transform.scale(self.frames[self.current_frame], (self.rect.width, self.rect.height))
               #print("current_frame:"+str(self.current_frame))
               if self.current_frame == 0:
                   self.frames.clear()
                   self.state = "idle"
                   print("idle")
                   self.end = time.time()
                   print("time:"+str(self.end - self.start))
                   img = pygame.image.load('./image/man.png')
                   self.image = pygame.transform.scale(img, (self.rect.width, self.rect.height))
                   pass
            
    # 加油动作手势
    def comeOn(self):
        # 加载mp4视频并提取图像帧
        #video = VideoFileClip("./mp4/1.mp4")
        frames = []
        '''
        video = cv2.VideoCapture("./mp4/1.mp4")
        # 设置帧计数器
        frame_count = 0
        while True:
            # 读取视频的每一帧
            ret, frame = video.read()
            # 如果没有读到帧,说明视频已经结束
            if not ret:
                break
            # 保存帧图片
            #cv2.imwrite(f'output/frame_{frame_count}.png', frame)
            #OpenCV转换成PIL.Image格式
            pil_image = Image.fromarray(cv2.cvtColor(frame,cv2.COLOR_BGR2RGB))
            image = remove(pil_image)
            image.save(f"framet_{frame_count}.png")
            # Convert PIL Image to pygame surface
            pygame_image = pygame.image.fromstring(image.tobytes(), image.size, image.mode).convert_alpha()
            
            frames.append(pygame_image)
            # 帧计数器自增
            frame_count += 1
        # 释放视频对象
        video.release()
        '''
        for i in range(0,75):
            img = pygame.image.load(f"./doc/img2/framet_{i}.png")
            frames.append(img)
        self.frames = frames
        print("frames count:"+str(len(self.frames)))
        self.current_frame = 0
        self.image = self.frames[self.current_frame]
        self.state = "comeOn"
        self.start = time.time()
    #再见动作手势
    def goodbye(self):
        pass

    #欢迎动作手势
    def welcome(self):
        pass
    #停止所有动作
    def stop(self):
        pass
    #开始说话
    def say(self):
        pass
        #sound = pygame.mixer.Sound('./sound/nihao.wav')
        #sound.play()

#背景
class BackGround(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load('./image/background.png').convert()
        self.image = pygame.transform.scale(self.image, (WIDTH, HEIGHT))
        self.rect = self.image.get_rect()
        self.ready_to_move = 0
        self.index = 0

    def update(self, *args):
        pass


# 初始化精灵组
bg_sprite = pygame.sprite.Group()
man_sprite = pygame.sprite.Group()

# 定义人物
man = VirtualMan(4)
man_sprite.add(man)

bg1 = BackGround()
bg_sprite.add(bg1)
# 保持游戏运行状态(游戏循环)
while True:
    # ===========游戏帧的刷新===========
    clock.tick(FPS)
    #print("Runtime:", pygame.time.get_ticks(), "ms")
    # 检测事件
    for event in pygame.event.get():
        # 检测关闭按钮被点击的事件
        if event.type == pygame.QUIT:
            # 退出
            pygame.quit()
            exit()
        if event.type == USER_EVENT:
           man.say()
           pass
        else:
            try:
                pass
            except Exception as e:
                print(e)
        
    # screen.fill((0,0,0))
    for group in [bg_sprite, man_sprite]:
        group.update()
        group.draw(screen)
    #screen.fill((0,0,0))    #生成一个屏幕  
    pygame.display.flip()
    #pygame.display.update()
    #app.paint()             #将pgu容器的内容画出

其他资源 

【代码抠图】4行Python代码帮你消除图片背景 - 知乎

【Python】推荐三个好玩的图像处理库_python rembg_赵卓不凡的博客-CSDN博客

百度安全验证

无需Photoshop!Rembg:图像背景自动去除工具_研道鸠摩智的博客-CSDN博客

数字人涌入直播间,虚拟主播的未来到底如何?

光生资讯 |虚拟数字人直播火热,前景广阔但仍需改进_进行_用户_问题

【Python】推荐三个好玩的图像处理库_python rembg_赵卓不凡的博客-CSDN博客

Python自动化:一款基于AI的自动图片背景去除软件 - 墨天轮

rembg 模型库放置位置设置_桑榆肖物的博客-CSDN博客

Matting库rembg使用测评 - 知乎

Python OpenCV 详解_pythonopencv-CSDN博客

Python+OpenCV计算机视觉全面基础概述(上篇) - 知乎

Py之cv2:cv2库(OpenCV,opencv-python)的简介、安装、使用方法(常见函数、方法等)最强详细攻略_顺其自然~的博客-CSDN博客

OpenCV视频操作 · OpenCV-Python初学自码 · 看云

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/287681.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【基础篇】九、程序计数器 JVM栈

文章目录 0、运行时数据区域1、程序计数器2、JVM栈3、JVM栈--栈帧--局部变量表4、JVM栈--栈帧--操作数栈5、JVM栈--栈帧--桢数据6、栈溢出7、设置栈空间大小8、本地方法栈 0、运行时数据区域 JVM结构里,类加载器下来,到了运行时数据区域,即Ja…

Linux用shell脚本执行乘法口诀表的两种方式

#!/bin/bash # *********************************************************# # # # * Author : 藻头男 # # * QQ邮箱 : 2322944912qq.com # …

数据库选择题 (期末复习)

2015期末 1、在数据库中,下列说法(A)是不正确的 A. 数据库避免了一切数据的重复 B. 数据库可以实现数据的独立性 C. 数据库中的数据可以共享 D. 数据库减少了数据冗余 2、事务日志一般用于保存(C) A. 程序运行过程 B…

怎么规划自己的现货白银交易生涯?

做现货白银交易不是儿戏的,应该对自己的生涯进行有效的规划,那么投资者如何规划自己的交易生涯呢?下面,我们将从资金管理和增长的角度来讨论一下。 首先我们讨论一下,在现货白银交易中应该如何管理盈利。我们应该要注意…

ByteTrack算法流程的简单示例

ByteTrack ByteTrack算法是将t帧检测出来的检测框集合 D {\mathcal{D}} D 和t-1帧预测轨迹集合 T ~ t − 1 {\tilde{T}_{t-1}} T~t−1​ 进行匹配关联得到t帧的轨迹集合 T t {T_{t}} Tt​。 首先使用检测器检测t帧的图像得到检测框集合 D {\mathcal{D}} D,再…

Oracle-增删改查

增删改 处理日期 oracle 处理date 类型 必须使用 to_date 函数或 sysdate oracle 与 mysql 处理 date 的区别mysql 中的 date 类型 只 支持 年月日, 使用 2000-10-01 oracle 中 date 类型 包含 年月日时分秒, 使用 to_date 函数to_date(1999-10-15,yyyy-MM-dd)​orac…

思科校园网搭建及配置综合小型实验

思科校园网搭建及配置综合小型实验 实验拓扑配置步骤配置聚合链路配置VTP,vlan域模板第一步 配置二层VLAN第二步 配置生成树第三步 配置相关IP地址第四步 配置DHCP及DHCP中继第五步 配置三层的网关冗余协议 双机热备及OSPF第六步 配置静态路由,NAT地址转换及其他配置…

STM32 ESP8266 物联网智能温室大棚 (附源码 PCB 原理图 设计文档)

资料下载: https://download.csdn.net/download/vvoennvv/88680924 一、概述 本系统以STM32F103C8T6单片机为主控芯片,采用相关传感器构建系统硬件电路。其中使用DHT11温湿度传感器对温度和湿度的采集,MQ-7一氧化碳传感器检测CO浓度,GP2Y101…

深度思考,AI项目的人工智能到底引领的是什么?

项目深度思考,人工智能到底引领的是什么? 人工智能引领技术之舞:项目深度思考项目背景:人工智能的魔法时代技术选择的深度思考:AI大决战团队协作的深度思考:AI联盟大会用户体验的深度思考:AI之光…

Redis命令---String篇 (超全)

目录 1.Redis Setnx 命令 - 只有在 key 不存在时设置 key 的值。简介语法可用版本: > 1.0.0返回值: 设置成功,返回 1 。 设置失败,返回 0 。 示例 2.Redis Getrange 命令 - 返回 key 中字符串值的子字符简介语法可用版本: > 2.4.0返回值: 截取得到…

Sigmaplot14安装包下载及安装教程

Sigmaplot 14下载链接:https://docs.qq.com/doc/DUnR0QmVzRVRXdGdB 1.鼠标右键解压到“Sigmaplot 14.0” 2.选中Sigmaplot14.0,鼠标右击选择“以管理员身份运行” 3.点击“Next” 4.选择I accept the terms of the license agreement,点击“N…

九州金榜|家庭教育中如何让孩子听话

心理学上有个专业名词叫做超限效应,是说如果外来刺激过多、过强或者是作用时间过久,就会让人感觉不耐烦,甚至是产生逆反心理。 这就是为什么现实生活中,很多父母就一件事唠叨无数遍,孩子依然不为所动的原因所在。 九…

Java获取windows操作系统基本信息

Java可以通过使用System类中的一些属性和方法来获取Windows操作系统的基本信息。以下是一些示例代码: public class WindowsInfo {public static void main(String[] args) {// 获取操作系统名称String osName System.getProperty("os.name");System.ou…

网络安全—IPSec安全策略

文章目录 网络拓扑添加策略ESP添加筛选器添加筛选器的操作另一台主机设置 AH 使用Windows Server 2003系统 网络拓扑 client1 IP 192.168.17.105client2 IP 192.168.17.106 只要保证两个主机在同一网段接口,即互相ping通即可完成策略的实现 下面的所有通讯都只是…

pytorch学习笔记

torchvision处理图像的 pytorch官网上看数据集的包,COCO数据集目标检测、语义分割,cifar物体识别 预训练好的模型 这个模块是图片的处理 root-位置,train-创建的true是个训练集,transform 前面是输出图片的数据类型,“…

在较高时间周期 这些现货黄金投资法值得一用

以日线图和周线图为代表的较高时间周期,一直是投资者很少利用的。之所以这么说,不是说投资者不会在日线图上分析,而是很少利用日线图交易。一来持仓过夜,会有相关的费用产生。二来很多人做现货黄金以短线为主。其实这种较高的时间…

【解决|三方工具】导入 XChart 后提示丢失关于 TMPPro 工具引用

开发平台:Unity 2021 版本 插件版本:XChart 3.0:官方文档 - https://github.com/XCharts-Team/XCharts   问题描述 导入 XChart 插件至 Unity 中出现 目录:Component、Theme 等提示丢失 TMPPro(TextMeshPro 工具&…

如何在ArcGIS Pro中指定坐标系

在进行制图的时候,为了实现某些特定的效果,需要指定特定的坐标系,但是现有的数据可能不是所需要的坐标系,这时候就需要对现有的数据坐标系进行处理,这里为大家介绍一下ArcGIS Pro中指定坐标系的方法,希望能…

Java经典框架之SpringSecurity

SpringSecurity Java 是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java 虚拟机,Java 仍是企业和开发人员的首选开发平台。 课程内容的介绍 1. SpringSecurity基本应用…

宏集七轴机械臂,以精准力控实现柔性抛光打磨!

(一)行业背景 传统的手工抛光打磨存在劳动强度高、抛光效果不稳定、难以处理复杂形状、安全风险和无法满足高质量要求等痛点。因此,应用工业机器人进行自动化表面精加工的技术随之崛起。 然而,打磨抛光领域一直难以实现全面的自动…