图形编辑器基于Paper.js教程17:图像转gcode前的处理,灰度,黑白,抖动

news2024/12/14 0:32:25

好久没有正经写博客了,前一段时间一直在备考中级项目管理,再加上项目开发只有自己一个人,每天忙的飞起。有闲暇时间也不想写,其中一部分原因也是因为很多简单问题,AI就能回答的很好。而对复杂的问题,也不是一两句话能够写清楚的。所以及时近期自己做了不少功能,能拿出来分享的也比较少。在这3个多月里,做了激光雕刻机的摄像头的定位,还有选择配件。
一个人做的真的累到要死,特别是团队里还没有能够理解自己的,攻克了一个难题也没有了什么成就感,你做出什么别人都觉得是正常的。

撤了那么多废话,其实就想告诉你们,人生事,不思八九,常想一二。

---------------正文分割线-------------

在激光雕刻机里,能雕刻的东西总体有两种元素,一种矢量元素,svg作为代表,一种是位图,png,jpg图片作为代表。

今天就来说一下如何将一张图片转换成gcode,使用激光雕刻机雕刻出来。

对于一张图片的每个像素,只有两种结果一种雕刻,一种事不雕刻。在GCode上表现为G0(不雕刻);G1(雕刻)。在颜色上就是白和黑。

那么我们首先获取一个图片的所有像素数据。一般使用ImageData来描述。

ImageData 描述了图片的每个像素RGBA四个通道,
这个数据会非常大,比如一个300300的图片,那么ImageData的数组长度就是 300 300*4 =360000。 如果是一个500万像素的照片,那就是一个2000万个元素的数组。

那么图片第一个像素的颜色就是
红色值 ImageData[0]
绿色值 ImageData[1]
蓝色值 ImageData[2]
透明值 ImageData[3]
以此类推。 每个值都是0到255

好现在我们拿到了图片上每个像素的颜色,在处理时我们不使用三种颜色,因为雕刻机只有黑和白。所以我们需要将四通道改为一通道,转换为灰色图。虽然这会丢失很多图片信息,但没办法。如果你的雕刻机能够雕刻出彩色的,那这一步就不需要转换为灰色。

转换为灰色后,图片的第一个像素点的灰度值如下:四个元素值相同,范围都是0-255。
灰色值 ImageData[0]
灰色值 ImageData[1]
灰色值 ImageData[2]
透明值 ImageData[3]

0为黑色,255 为白色。
彩色转灰色 有一个公式
Gray=0.299⋅R+0.587⋅G+0.114⋅B

js的函数实现

/**
 * 将图像的每个像素转换为灰度
 * @param {HTMLImageElement} image - 要转换的图像
 * @param {HTMLCanvasElement} canvas - 目标 canvas 元素
 */
function convertImageToGrayscale(image, canvas) {
  const ctx = canvas.getContext('2d');
  // 将图像绘制到 canvas 上
  canvas.width = image.width;
  canvas.height = image.height;
  ctx.drawImage(image, 0, 0);
  
  // 获取图像的像素数据
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  const data = imageData.data;

  // 遍历每个像素(每个像素由4个分量组成:R、G、B、A)
  for (let i = 0; i < data.length; i += 4) {
    const r = data[i];     // 红色通道
    const g = data[i + 1]; // 绿色通道
    const b = data[i + 2]; // 蓝色通道

    // 计算灰度值(加权公式)
    const gray = 0.299 * r + 0.587 * g + 0.114 * b;

    // 将 R、G、B 替换为灰度值,A 保持不变
    data[i] = data[i + 1] = data[i + 2] = gray;
  }

  // 将灰度图像数据放回 canvas
  ctx.putImageData(imageData, 0, 0);
}

好现在你得到了一个灰度图,除去透明度,(这个确实没办法,你总不能激光能够雕刻出透明的效果来。)一张图片的所有像素就变成了一个一维数组来描述。每个元素的值为0-255。那么怎么规定哪些像素该雕刻,哪些像素不雕刻。0-255 的中间值是 128。 这个就是阈值。
小于128的像素我们就雕刻变成黑色,
大于128的像素我们就不雕刻,保持材料原来的颜色。

黑白图也是这样的来的。
下面我给你看一下原图,灰度图,黑白图的区别。

在这里插入图片描述
上面这个是原图,我最近在做的旋转配件测试。

把这图片进行灰度化后就变成了下面的效果
在这里插入图片描述
上面的就是灰色图,这让我想起了小时候家里的黑白电视。
当我们将0-255的灰色通过阈值128 处理后,就变成了只有0和255的两值图片,真正的黑白照片,只有黑白。下面的就是黑白图片,会都是很多细节。
在这里插入图片描述
到了这里你就已经能够雕刻出图片啦,虽然会丢失很多细节。那么接下来就要思考 如何在只有黑白两种颜色的情况下尽可能多地展示图片的细节?

我在这里也卡了很久,通过查阅资料 得知了抖动这一图片算法。它的原理是在使用一个卷积 ,将灰度值的误差扩散到相邻的几个像素上。增一下一些黑色的小白点,我们可以把它叫做噪点,它会欺骗我们的眼睛,让我们觉得图片会不同层次的灰度。增加噪点的规律是 在特别黑的地方,越黑的地方早点增加的越多,越白的地方噪点越少。

灰度值的误差是这样计算的, 比如当前像素的灰度值是200,那么它应该转换为255,误差是55,将这个误差55,加到相邻的上下左右的像素上。
经典抖动卷积核

     X   7/16
  3/16   5/16  1/16

X 代表当前像素(当前位置)。
右边和下面的像素接收当前像素的误差,权重之和为 1。
公式的含义是将当前像素的“误差”分配到相邻像素,以在视觉上减少色彩深度丢失的影响。

下面看一下经过抖动算法处理的图片
在这里插入图片描述
虽然上面的图片也只有黑白两个颜色,但是和灰度图表现的细节相差无几。

整体看下四个图片
在这里插入图片描述
另一个例子
在这里插入图片描述
最终的雕刻效果(自己去试吧,雕刻图片会吸不少甲醛)

获取到了抖动图后,后面就比较简单了,就是遍历数组,数组的元素 只有两个值0 和255。
遇到0 就用G1,遇到255 就用G0

最终形成了图片的GCode

如果有人对图片GCode,位图转GCode,雕刻图片感兴趣的话,后面再写一个优化图片GCode,双向雕刻,过滤白色行,相对路径雕刻图片。
今天这篇文章就写到这里啦。

最后就是 我的项目管理考试过了,哈哈 不枉我复习了2个月多,每天背着600多页的书。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI大模型学习笔记|人工智能的发展历程、智能体的发展、机器学习与深度学习的基本理论

学习链接&#xff1a;冒死上传&#xff01;价值2W的大模型入门到就业教程分享给大家&#xff01;轻松打造专属大模型助手&#xff0c;—多模态、Agent、LangChain、ViT、NLP_哔哩哔哩_bilibili 百度网盘自己整理的笔记&#xff1a; 通过网盘分享的文件&#xff1a;1-人工智能的…

qt 设置系统缩放为150%,导致的文字和界面的问题

1 当我们设置好布局后&#xff0c;在100%的设置里面都是正常的&#xff0c;但是当我们修改缩放为150%后&#xff0c;字体图标&#xff0c;界面大小就出现问题了&#xff0c;这就需要我们设置一些参数。 QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);QCoreAppl…

linux-15 关于shell(十四)printenv,hash,环境变量

此前没有用过linux&#xff0c;可能有些觉得很奇怪&#xff0c;就觉得我们在这敲来敲去命令干什么&#xff1f;为什么不使用双击这种方式来操作&#xff1f;大家知道&#xff0c;在Windows里面&#xff0c;其实我们双击也无非就是告诉我们shell需要将这个命令发送在内核上启动的…

虚拟机如何使用物理机的公私钥

一、生成公私钥&#xff08;如果没有的话&#xff09; 使用如下指令生成 生成RSA公私钥 ssh-keygen 生成EdDSA公私钥 ssh-keygen -t ed25519 Windows目录 linux会直接生成在当前目录下。 二、导出 一般都是从windows系统导入到linux系统。 可以直接将公私钥文件复制到虚拟机…

SpringBoot【十一】mybatis-plus实现多数据源配置,开箱即用!

一、前言&#x1f525; 环境说明&#xff1a;Windows10 Idea2021.3.2 Jdk1.8 SpringBoot 2.3.1.RELEASE 正常情况下我们在开发系统的时候都是使用一个数据源&#xff0c;但是由于有些项目同步数据的时候不想造成数据库io消耗压力过大&#xff0c;便会一个项目对应多个数据源…

前端报错npm ERR cb() never called问题

环境使用node版本v14.21.3&#xff0c;npm版本6.14.18 1.问题描述 1.1使用npm install后报错 npm ERR! cb() never called!npm ERR! This is an error with npm itself. Please report this error at: npm ERR! ? ? <https://npm.community>npm ERR! A complete log…

C++ STL Cookbook STL算法

目录 std::copy 将容器元素合并为一个字符串 使用 std::sort 对容器进行排序 使用 std::transform 修改容器 在容器中查找项目 使用 std::sample 采样数据集 (写在前面&#xff1a;笔者前段时间备战考试和比赛了&#xff0c;现在回来继续更新) STL实际上提供了非常非常丰…

SpringBoot【十】mybatis之xml映射文件>、<=等特殊符号写法!

一、前言&#x1f525; 环境说明&#xff1a;Windows10 Idea2021.3.2 Jdk1.8 SpringBoot 2.3.1.RELEASE 在利用mybatis进行开发的时候&#xff0c;编写sql时可能少不了>、<等比较符号&#xff0c;但是在mapper映射文件中直接使用是不行的&#xff0c;会报错&#xff0…

单元测试SpringBoot

添加测试专用属性 加载测试专用bean Web环境模拟测试 数据层测试回滚 测试用例数据设定

每天40分玩转Django:简介和环境搭建

Django简介和环境搭建 一、课程概述 学习项目具体内容预计用时Django概念Django框架介绍、MVC/MTV模式、Django特点60分钟环境搭建Python安装、pip配置、Django安装、IDE选择45分钟创建项目项目结构、基本配置、运行测试75分钟实战练习创建个人博客项目框架60分钟 二、Djang…

Jenkins参数化构建详解(This project is parameterized)

本文详细介绍了Jenkins中不同类型的参数化构建方法&#xff0c;包括字符串、选项、多行文本、布尔值和git分支参数的配置&#xff0c;以及如何使用ActiveChoiceParameter实现动态获取参数选项。通过示例展示了传统方法和声明式pipeline的语法 文章目录 1. Jenkins的参数化构建1…

Windows安装WSL子系统及docker,以及WSL和docker配置、使用及问题解决

在Windows操作系统中,Ubuntu子系统(也称为Windows Subsystem for Linux, WSL)为开发者提供了一个在Windows环境下运行Linux环境的平台。然而,有时用户在按照Ubuntu子系统或者使用WSL时,可能会遇到各种问题,下面总结一下解决方式。 想要在Windows上安装Docker(实际上是基…

Linux中的线程

目录 线程的概念 进程与线程的关系 线程创建 线程终止 线程等待 线程分离 原生线程库 线程局部存储 自己实现线程封装 线程的优缺点 多线程共享与独占资源 线程互斥 互斥锁 自己实现锁的封装 加锁实现互斥的原理 死锁 线程同步 线程的概念 回顾进程相关概念 …

shell编程(完结)

shell编程&#xff08;完结&#xff09; 声明&#xff01; 学习视频来自B站up主 ​泷羽sec​​ 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章 笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其…

ctfshow-web 151-170-文件上传

151. 我们首先想到就是上传一句话木马。但是看源代码限制了png。 &#xff08;1&#xff09;改前端代码。 这里是前端限制了上传文件类型&#xff0c;那我们就改一下就好了嘛,改成php。 这里直接修改不行&#xff0c;给大家推荐一篇简短文章&#xff0c;大家就会了&#xff08…

Docker的初识

目录 1. 容器技术发展史1.1 Jail 时代1.2 云时代1.3 云原生时代1.3.1 Google & Docker 竞争1.3.2 k8s 成为云原生事实标准 2. 虚拟化和容器化的概念2.1 什么是虚拟化、容器化2.2 为什么要虚拟化、容器化&#xff1f;2.3 虚拟化实现方式2.3.1 应用程序执行环境分层2.3.2 虚拟…

Jenkins流水线初体验(六)

DevOps之安装和配置 Jenkins (一) DevOps 之 CI/CD入门操作 (二) Sonar Qube介绍和安装(三) Harbor镜像仓库介绍&安装 (四) Jenkins容器使用宿主机Docker(五) Jenkins流水线初体验(六) 一、Jenkins流水线任务介绍 之前采用Jenkins的自由风格构建的项目,每个步骤…

链式设计模式——装饰模式和职责链模式

一、装饰模式 1、概述 动态地给一个对象添加一些额外的职责&#xff0c;就增加功能来说&#xff0c;装饰模式比生成子类更为灵活。 ConcreteComponent &#xff1a;是定义了一个具体的对象&#xff0c;可以给这个对象添加一些职责&#xff1b;Decorator &#xff1a;装饰抽象…

JavaEE多线程案例之阻塞队列

上文我们了解了多线程案例中的单例模式&#xff0c;此文我们来探讨多线程案例之阻塞队列吧 1. 阻塞队列是什么&#xff1f; 阻塞队列是⼀种特殊的队列.也遵守"先进先出"的原则. 阻塞队列是⼀种线程安全的数据结构,并且具有以下特性: 当队列满的时候,继续⼊队列就会…

【Linux】VMware 安装 Ubuntu18.04.2

ISO镜像安装步骤 选择语言 English 选择键盘布局 English 选择系统 Ubuntu 虚拟机网卡地址&#xff0c;默认即可 代理地址&#xff0c;默认空即可 镜像地址&#xff0c;修改成阿里云地址 选择第二项&#xff0c;LVM 磁盘扩容技术 第一块硬盘名sda&#xff0c;默认…