Bad Apple --MSC Patran版

前言:本来想通过MPC连接,定义基于时间的位移约束,进行时域分析,然后形成动画的。结果位移约束没搞好,所以改用“显示/隐藏”这个简单方案。考虑到动画的帧数,放弃第一个方案也许是跟明智的。

基本思路:
1、获取动画的各帧点阵图。
2、编写PCL的显示、隐藏命令。
3、执行动画。

具体方法:
1、将视频转换为各帧图片保存;
2、读取各帧图片,调整像素,转换为黑白图片;
3、获取各点灰度;
4、根据灰度大小分为黑、白;
5、根据“黑”、“白”定义方块的显示或隐藏,写入文本;
6、在Patran中建立显示框;
7、读取PCL;
8、录视频、合音轨、炫耀……

选择Python只是好玩,但是用了之后发现,真的是“人生苦短,……”

以下是具体方案:
一、获取点阵图
直接通过opencv进行处理,获取各帧图。
关键代码(根据网上搜到的代码改的):

import cv2

vc = cv2.VideoCapture(r'F:\WorkSpace\resources\bad apple.flv') #读入视频文件
c=1
if vc.isOpened(): #判断是否正常打开
    rval , frame = vc.read()
else:
    rval = False
print(rval)
while rval:   #循环读取视频帧
    rval, frame = vc.read()
    print("timeF")
    cv2.imwrite('a/'+str(c) + '.jpg',frame) #存储为图像
    c = c + 1
vc.release()

把存储的图像再转换为点阵图即可,获取文件→图片放缩→转换为灰白图像→获取各像素点值。

在获取文件时,需要注意,通过glob获取文件时,并不是按照我们期望的顺序,即“1,2,…,9,10,11”这种,而是“1,10,11,2,…”这种。需要进行排序。
Python里,可参考如下方式。
(来自“https://blog.codinghorror.com/sorting-for-humans-natural-sort-order/”)
(来自“https://nedbatchelder.com/blog/200712/human_sorting.html”)

def atof(text):
    try:
        retval = float(text)
    except ValueError:
        retval = text
    return retval

def natural_keys(text):
    '''
    alist.sort(key=natural_keys) sorts in human order
    http://nedbatchelder.com/blog/200712/human_sorting.html
    (See Toothy's implementation in the comments)
    float regex comes from https://stackoverflow.com/a/12643073/190597
    '''
    return [ atof(c) for c in re.split(r'[+-]?([0-9]+(?:[.][0-9]*)?|[.][0-9]+)', text) ]

Python确实简洁。其他语言可能会代码量稍多。
然后对获取的文件列表,循环对每个文件进行处理。
关键代码如下:

def transform1(image_file):
    image_file = image_file.convert("L")  # 转换为黑白图片,参数"L"表示黑白模式
    codePic = ''
    for h in range(0, image_file.size[1]):  # size属性表示图片的分辨率,'0'为横向大小,'1'为纵向
        for w in range(0, image_file.size[0]):
            gray = image_file.getpixel((w, h))  # 返回指定位置的像素,如果所打开的图像是多层次的图片,那这个方法就返回一个元组

            if gray > 170:
                codePic = codePic + " " + ' '
            else:
                codePic = codePic + " " + "■"

        codePic = codePic + '\r\n'
    return codePic
for image in image_list:
    im = Image.open(image)
    im = im.resize((60, 45))
    gray1 = transform1(im)

进行图片转换,获取各像素点灰度,没什么好说的。

二、建立Patran显示板
通过PCL语言或者手动建立均可。
在XOY平面内依次建立各显示点,这里使用的是立方体,可能用2D的CAD对象或使用单元对象显示效率更高吧,没有试,有兴趣的同学可以试试。
保持与Python图像顺序一致,序号安装从左向右,从上向下。
PCL代码如下:

STRING ge_create_solid_pri_created_ids[VIRTUAL]
ge_const_solid_block( "1", "1.0", "1.0", "1.0", 0, "", "Coord 0", "[0 0 0]",  @
ge_create_solid_pri_created_ids )
$# 1 Solid Created: Solid 1
STRING sgm_transform_solid_created_ids[VIRTUAL]
$向X方向进行平移,执行59次
ge_transform_translate_v1( "", "solid", "<1 0 0>", 1., FALSE, "Coord 0", 59, FALSE, "Solid 1", sgm_transform_solid_created_ids )
write(sgm_transform_solid_created_ids)
STRING sgm_transform_solid_created_ids[VIRTUAL]
$向-Y方向进行平移,执行44次
ge_transform_translate_v1( "", "solid", "<0 -1 0>", 1., FALSE, "Coord 0", 44, FALSE, "Solid 1:60", sgm_transform_solid_created_ids )
write(sgm_transform_solid_created_ids)

$修改背景颜色,默认是蓝色,这里修改为白色(可能是这个功能,想不起来了...)
uil_imaging_bw_reverse(  )
ui_repaint_tree( TRUE )
uil_imaging_bw_reverse(  )
ui_repaint_tree( TRUE )

$设置当前默认组的颜色为黑色,不显示边缘线
ga_group_color_set( "default_group", 7 )
coloring_method( 2 )
ga_display_showedges_set( "general", 0 )

$设置显示模式,设置视角和范围
uil_toolbar.shaded_smooth(  )
ga_view_aa_set( 0., 0., 0. )
gu_fit_view(  )

三、动画效果
通过执行PCL进行动画。
前面提到的,最初希望能够通过时域分析得到,显得屌屌哒,然后放弃了。
通过PCL显示动画就简单多了,把像素点移动至屏幕外,显示隐藏,移出当前组都可以实现。
开始使用的是移出/移入当前组,即“ga_group_entity_remove”,后来感觉像素点多了执行有点慢,就采用显示/隐藏,“gm_visibility_widget”。效果还不错。
注意的是,显示/隐藏后,需要刷新画面才能显示正常,可以使用“ga_view_aa_set( 0., 0., 0. )”进行刷新。
所以,每一帧的处理逻辑基本上就是:像素点设置为显示→刷新→像素点设置为隐藏→下一次循环。

每一帧动画之间,可以进行停顿。
方法1:
通过调用“utl_process_spawn”执行外部程序实现,当“utl_process_spawn”参数为“TRUE”时,Patran会等待该程序执行结束。
这里写图片描述
在与Patran交互时,通过该方式能够实现Patran与外部程序间的相互触发。
方法2:
直接通过Patran中的循环等待即可。
编写While循环,然后判断时间即可,通过“sys_cputime()”获取时间进行判断。
然后,出现的问题是,每一帧的执行时间基本上与帧时间一致,所以,根本不需要停顿。而且每一帧的执行时间也可能不一致……

四、建立PCL动画文件
这里就简单了,通过Python把各帧需要显示的solid编号写入PCL文件即可。Python的格式化输出“.format”还是很方便的。
各帧的核心代码如下:

    f.write("gm_visibility_widget(\"Solid {} \", TRUE)".format(gray2) + "\n")
    f.write("ga_view_aa_set( 0., 0., 0. )" + "\n")
    f.write("gm_visibility_widget(\"Solid 1:2700 \", FALSE)" + "\n")

这里需要注意的是,在进行显示设置时,我们的显示对象“Solid”一般为“Solid 1 2 3 4”这种形式,对Patran来说这个格式是没有问题的,但是PCL文件对各行长度是有限制的,具体长度未测试。所以对于长文本需要通过“@”进行连接,所以在处理图像时,可以直接获取如下格式的实体编号。

num = num + str(h * 60 + w + 1) + " " + "\"" + r"//@" + """
gm_visibility_widget("Solid  1 "//@
                "  2 "//@
                "  3 "//@
                "  4 "//@
                "  5 "//@
                "  6 "//@

这样可以保证不会长度超限,然后结果就是,PCL文件比较大……这里6000+图片,80*60的点,PCL文件达到了500M+。
压缩与不压缩的对比
其实可以通过简写为“Solid 1:10 12”这种形式,可以大幅度减少PCL大小。
通用处理方式为:去重→排序→简化。
处理之后PCL文件会减小很多,但是依旧有可能长度超出,所以需要判断长度,进行“@”分割。…所以算了。

五、后处理
然后就是录视频,音频视频合并,等等。
win10自带的录制还不错,自动识别Patran窗口并只录制窗口内容。
效果基本上就是这样:https://www.bilibili.com/video/av17717423/
然而根本没有人看……

资源
PCL文件:http://download.csdn.net/download/lk1233691/10183172
现在不能0分分享了,所以外加度娘盘。
https://pan.baidu.com/s/1kULUAWZ
Python代码:http://download.csdn.net/download/lk1233691/10183179

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值