当前位置: 首页 > news >正文

用 Manim 重现有趣的知觉错觉

1. 静态的欺骗

这三种错觉不需要动画,仅仅通过静态的排列和色彩对比,就能欺骗我们的大脑。

1.1. 彩纸屑错觉

这是David Novick创作的Munker错觉的变体。

下面图中所有的圆圈颜色完全相同,唯一不同的是围绕它们的线条颜色。

这个错觉生动地证明:我们并非直接感知物体在现实中的颜色。相反,知觉系统会根据物体周围的环境,做出一个有根据的"猜测"。

1.2. 米饭波浪错觉

这看起来像是一个动态GIF,但其实不是。所有的"运动"都发生在你的大脑中。

它的作者:Akiyoshi Kitaoka

黄色斑块的阴影和排列顺序会触发大脑的运动感知区域,从而在一个实际静止的图像中产生运动的知觉。有趣的是,大约5%的人似乎对这个错觉"免疫"。

1.3. 倾斜道路错觉

这看起来像是从不同角度拍摄的同一道路的两张照片。但实际上,这只是同一张照片复制了两次。

显然,视觉系统将这张图像当作两张独立道路的照片来处理。在二维图像中,两条道路的轮廓是相互平行的。

如果现实世界中的两条道路在图像中呈现这种效果,那么它们在现实中必须是强烈地向外倾斜的。因此,视觉系统便做出了这样的推断。

2. 动态的魔法

接下来,我们使用Manim来制作后两种动态错觉。

2.1. 动态艾宾浩斯错觉

图中的橙色圆圈实际上并没有改变大小。

与颜色和明度一样,我们并非直接感知物体的大小。知觉系统会根据感官数据中的线索(包括附近其他物体的相对大小)来推断物体的尺寸。

Manim代码:

from manim import * config.background_color = WHITE class DynamicEbbinghaus(Scene): def construct(self): # 中心圆圈(实际大小不变) center_circle = Circle(radius=0.3, color=ORANGE, fill_opacity=1) center_circle.set_stroke(width=0) center_circle.move_to(LEFT * 2 + UP * 2) center_circle2 = center_circle.copy() center_circle2.move_to(ORIGIN) # 周围圆圈 surrounding_circles = VGroup() surrounding_circles2 = VGroup() num_circles = 6 radius = 0.1 distance = 0.4 radius2 = 0.7 distance2 = 1.5 for i in range(num_circles): angle = i * (360 / num_circles) * DEGREES circle = Circle(radius=radius, color=PURE_BLUE, fill_opacity=1) circle.set_stroke(width=0) circle.move_to( center_circle.get_center() + distance * np.array([np.cos(angle), np.sin(angle), 0]) ) surrounding_circles.add(circle) circle2 = Circle(radius=radius2, color=PURE_BLUE, fill_opacity=1) circle2.set_stroke(width=0) circle2.move_to( center_circle2.get_center() + distance2 * np.array([np.cos(angle), np.sin(angle), 0]) ) surrounding_circles2.add(circle2) self.add(center_circle, surrounding_circles) self.wait(0.5) a_group = VGroup(center_circle, surrounding_circles) a_group2 = a_group.copy() b_group = VGroup(center_circle2, surrounding_circles2) # 正常移动 self.play(a_group.animate.move_to(b_group.get_center()), run_time=2) self.play(a_group.animate.move_to(a_group2.get_center()), run_time=2) self.wait(1) # 放大蓝色小圆 # 动画:周围圆圈变大,使中心圆圈看起来变小 self.play( ReplacementTransform(a_group, b_group), run_time=2, ) # 动画:周围圆圈变小,使中心圆圈看起来变大 self.play( ReplacementTransform(b_group, a_group2), run_time=2, ) self.wait(1)

2.2. 动态穆勒-莱尔错觉

这是我见过最棒的错觉之一。蓝色和红色的线条长度完全相同;没有任何线条在移动或改变大小,它们都处于同一水平线上。只有两端的箭头在移动。

这个错觉是经典"穆勒-莱尔错觉"的新变体。关于它的原理有许多理论,但没有人能100%确定。甚至还存在争议:这种错觉是适用于全人类,还是某种特定文化下的现象?

Manim代码:

from manim import * import numpy as np config.background_color = WHITE class DynamicMullerLyer(Scene): def construct(self): self.vertexes = [] count = 11 # 所有线都一样长,蓝色和红色的线段也是一样长。 lines = self.create_lines(count) self.play(Create(lines)) self.wait(1) self.clear() wings = self.create_wings(self.vertexes) self.add(*wings) self.rotate_wings( wings, self.vertexes, list(np.random.uniform(0.5, 1.5, len(wings))), repeat=4, ) self.wait(1) # 放在一起 self.add(lines) self.rotate_wings( wings, self.vertexes, list(np.random.uniform(0.5, 1.5, len(wings))), repeat=8, ) self.wait(0.5) def create_lines(self, count=11, interval=0.4) -> VGroup: l_group = VGroup() for i in range(count // 2 + 1): vertical_l_group = VGroup() vertical_l_group.add( Line(UP * 2.5, UP * 1.5, stroke_width=2, color=PURE_BLUE) ) vertical_l_group.add( Line(UP * 1.5, UP * 0.5, stroke_width=2, color=PURE_RED) ) vertical_l_group.add( Line(UP * 0.5, DOWN * 0.5, stroke_width=2, color=PURE_BLUE) ) vertical_l_group.add( Line(DOWN * 0.5, DOWN * 1.5, stroke_width=2, color=PURE_RED) ) vertical_l_group.add( Line(DOWN * 1.5, DOWN * 2.5, stroke_width=2, color=PURE_BLUE) ) vertical_l_group.shift(LEFT * i * interval) self.vertexes.append(UP * 2.5 + LEFT * i * interval) self.vertexes.append(UP * 1.5 + LEFT * i * interval) self.vertexes.append(UP * 0.5 + LEFT * i * interval) self.vertexes.append(DOWN * 0.5 + LEFT * i * interval) self.vertexes.append(DOWN * 1.5 + LEFT * i * interval) self.vertexes.append(DOWN * 2.5 + LEFT * i * interval) l_group.add(vertical_l_group) for i in range(1, count // 2 + 1): vertical_l_group = VGroup() vertical_l_group.add( Line(UP * 2.5, UP * 1.5, stroke_width=2, color=PURE_BLUE) ) vertical_l_group.add( Line(UP * 1.5, UP * 0.5, stroke_width=2, color=PURE_RED) ) vertical_l_group.add( Line(UP * 0.5, DOWN * 0.5, stroke_width=2, color=PURE_BLUE) ) vertical_l_group.add( Line(DOWN * 0.5, DOWN * 1.5, stroke_width=2, color=PURE_RED) ) vertical_l_group.add( Line(DOWN * 1.5, DOWN * 2.5, stroke_width=2, color=PURE_BLUE) ) vertical_l_group.shift(RIGHT * i * interval) self.vertexes.append(UP * 2.5 + RIGHT * i * interval) self.vertexes.append(UP * 1.5 + RIGHT * i * interval) self.vertexes.append(UP * 0.5 + RIGHT * i * interval) self.vertexes.append(DOWN * 0.5 + RIGHT * i * interval) self.vertexes.append(DOWN * 1.5 + RIGHT * i * interval) self.vertexes.append(DOWN * 2.5 + RIGHT * i * interval) l_group.add(vertical_l_group) return l_group def create_wings(self, vertexes, wing_radio=0.1): groups = [] # 创建两条线,呈V字形 for vertex in vertexes: left_line = Line( vertex, vertex + (UP + LEFT) * wing_radio, stroke_width=2, color=BLACK ) right_line = Line( vertex, vertex + (UP + RIGHT) * wing_radio, stroke_width=2, color=BLACK ) groups.append(VGroup(left_line, right_line)) return groups def rotate_wings(self, wings, vertexes, run_times, repeat=4): anims = [] for i in range(len(wings)): ag1 = AnimationGroup( Rotate( wings[i][0], angle=90 * DEGREES, about_point=vertexes[i] ).set_run_time(run_times[i]), Rotate( wings[i][1], angle=-90 * DEGREES, about_point=vertexes[i] ).set_run_time(run_times[i]), ) ag2 = AnimationGroup( Rotate( wings[i][0], angle=-90 * DEGREES, about_point=vertexes[i] ).set_run_time(run_times[i]), Rotate( wings[i][1], angle=90 * DEGREES, about_point=vertexes[i] ).set_run_time(run_times[i]), ) anim = Succession([ag1, ag2] * repeat) anims.append(anim) self.play( AnimationGroup(*anims), run_time=max(run_times) * repeat, )

3. 总结

这些错觉共同揭示了一个深刻的事实——我们的知觉并非对世界的“直接复制”,而是大脑基于有限感官信息、结合经验与期望所构建的“最佳猜测模型”。

通过Manim重现这些错觉,我们不仅理解了视觉心理学,也掌握了如何用代码精确控制视觉元素来传达信息。

http://www.jsqmd.com/news/564135/

相关文章:

  • 别再只盯着线程数了!JMeter压力测试实战:从单接口到混合场景的完整配置与结果分析
  • 万象视界灵坛效果展示:多候选标签间语义冲突检测与消歧建议生成
  • GLM-4.1V-9B-Base一文详解:与Qwen-VL、InternVL2中文视觉理解对比
  • 亲测中山口碑好的可靠手机维修企业
  • 像素艺术爱好者的福音:忍者像素绘卷(天界画坊)保姆级入门
  • RK3588开发板摄像头实战:从MIPI到USB的完整配置指南(附设备树修改技巧)
  • TensorFlow-v2.9镜像新手教程:M1芯片AI开发环境配置
  • 【office2pdf】office2pdf - 产品需求文档 (PRD.md)
  • 手机也能玩转Llama3.1!用Cpolar穿透实现移动端访问LobeChat的5个技巧
  • 无需安装即可畅享B站视频:downkyi绿色版全方位使用指南
  • RTX 4090D专属优化!Wan2.2-I2V-A14B私有部署镜像,小白也能快速上手
  • 使用CMake与vcpkg简化C/C++项目依赖管理
  • 2026AI大淘汰前夜:3个自动化技能让你年薪翻倍,成为筛不掉的职场金粉!
  • VideoAgentTrek-ScreenFilter视频智能过滤实战:基于卷积神经网络的实时画面处理
  • RealRestorer:AI修复真实图像的终极利器
  • Windows Subsystem for Android实战指南:从环境配置到核心功能落地的系统方案
  • 代理IP:按流量还是按IP/时长计费更划算?
  • Flutter项目卡在‘assembleDebug’?Gradle配置优化全攻略
  • Phi-4-Reasoning-Vision入门必看:双卡4090环境配置与THINK/NOTHINK模式详解
  • OWL ADVENTURE系统清理与维护:释放C盘空间与优化存储
  • 产品好却卖不动?90%的小团队都死在这一步
  • 微信小程序集成AI能力:调用LFM2.5-1.2B-Thinking-GGUF实现智能聊天与内容生成
  • Qwen3-ASR-0.6B部署教程:腾讯云TI-ONE平台GPU训练/推理一体化部署流程
  • RWKV7-1.5B-g1a效果展示:‘请用一句中文介绍你自己’真实响应
  • AI头像生成器镜像优化:Qwen3-32B 4-bit量化后8GB显存稳定运行实录
  • 突破Windows XP/2003兼容性壁垒:One-Core-API-Source革新方案解析
  • OFA视觉问答模型镜像免配置:3条命令启动,告别pip install地狱
  • OFA模型在零售行业的视觉问答应用案例
  • 【Linux的以太网驱动的收发流程比较】
  • 新手也能上手!盘点2026年倍受青睐的AI论文软件