首页
友情链接
点点滴滴
关于本站
秋码记录
一个游离于山间之上的Java爱好者 | A Java lover living in the mountains
累计撰写
144
篇文章
累计创建
323
个标签
累计创建
47
个分类
栏目
首页
友情链接
点点滴滴
关于本站
搜索
canvas绘制文本时,该如何处理首行缩进、自动换行、多内容以省略号结束、竖排的呢?
实现如标题所示的这些文本效果,在css看来,不就是一两行css属性。然而,对于canvas来讲,要想呈现这样的文字样式,就没css那么轻松简便了。 既然如此,那为何还要使用对文本支持度不友好的canvas来绘制文字呢?而不是采用对文本天然支持的css呢? canvas 绘制文本的场景 在给为何弃对文本天然支持的 css而不用,拣起了文本支持度不友好的canvas的答复之时。不妨先来看看,究竟是在什么样的场景下,需要用到canvas去绘制文本呢? 常逛商场的,总会不时地看到一些商家为了吸引客流而制作出的一张精美海报;再看艺术展前,也总能在大门看到本次参展的“艺术家”们最为得意的艺术及简介,所绘制的一张海报;去电影院观看的,大都是被该片前期在各大商场及公共场合宣传的那张海报而吸引来的。…… 是咯,照这样看来,海报的确可以作为事物的重要途径,虽然海报承载的内容有限,但一张足够优美的海报,总是能把人们的目光给吸引过来的,好比去书店买书,总是会翻到书的背面。 甭管对前沿技术的学习,抑或是为了解决问题而去搜寻资料,你总免不了在各大博客(如:秋码记录 )、论坛、社区以及生活类情感博客等网站游离,那些博文、贴文等总能解决你的燃眉之急的问题,而你也会在兴奋之余随手将该文分享给朋友。 很显然,文章分享功能可以说是各大网站的基础功能,网站运营者也热衷于你把文章分享出去,从而悄无声息的向你朋友推荐了该网站。所以,网站运营者是绝不会错失这样一个向用户宣传网站媒介之一的机会。然而,社会分享组件(第三方分享:诸如 QQ、微信、微薄……)并不能很好的推介网站,基于这种状况,一张既有文章的概要,又有网站的简介的海报便应运而生了。(秋码记录 便能为文章生成一张精美的海报)。 网站生成海报的几种方案 无论是线下的,还是线上的海报,它都是一张图。对于线下,想要制作出一张海报,只需将事先做好的海报图打印出来即可,但就线上而言,网站页面结构主要由html、css、javascript构成,而文章内容及文章封面图都是不一样的,那么,在这样的情况下,又该如何为文章生成一张海报呢? 既然知道了,海报是一张图,而文章页面结构又是html,那么只需将html转变成图不就成了吗? 没错,要想为文章生成海报,只需把html转成图片即可,而且还有开源的第三方实现。 1、html2canvas.js:从其命名上来看,一眼便能知晓,它是将页面的html转成canvas。这也是众多网站生成海报的首选之一。它的便捷在于你想要为海报生成什么款式的,你只需像修改你网站那样去修改就好。(目前 秋码记录 是采用这种方式来为文章生成海报) 2、dom-to-image.js:与html2canvas.js大致差不多。 3、canvas:直接使用canvas绘制而生成的海报,基于wordpress的很多主题也都使用它来生成海报。( 秋码记录 即将采用这种方案) canvas绘制文本 在使用canvas绘制文本之前,有必要了解下什么是canvas? 其实,canvas也是作为html标签而存在于html结构中,而它常常被用来绘制图形及图形动画。 在现实生活中,艺术家想要画出一张画,有两样东西是必不可少的——素描纸(写生纸)、HB铅笔。 而在canvas中,同样需要设置画布的大小——width、height。 canvas绘制文本API CanvasRenderingContext2D.fillText(text, x, y [, maxWidth]); text : text是需要绘制的文本。 x : x是文本绘制的水平参考点坐标。随着CanvasRenderingContext2D.textAlign的设置不同,x的坐标位置也不同。可以表示这段文字内容左侧坐标,或水平中心坐标,或右侧坐标。 y : y是文本绘制的垂直参考点坐标。随着CanvasRenderingContext2D.textBaseline的设置不同,y的坐标位置也不同。支持多种基线类型(CSS中也有对应概念),MDN上有一张图可以很好地表示文本基线和文本垂直位置的关系。 **maxWidth**: maxWidth表示文本内容占据的最大宽度。这里的maxWidth概念和CSS中的max-width差别很大,其最终的文本表现是:当文本占据宽度超过maxWidth的后,所有的文本自动变窄以适应这个最大宽度限制。表现类似这样: canvas 如何实现文本首行缩进、自动换行、内容过多省略号呢? 虽然到目前为止,canvas API中还并没有提供文本首行、自动换行、内容过多以省略号结束等的支持,但还是可以通过计算X Y偏移量来实现的。 首行缩进 对于文本首行缩进,也就是在首行空出相对应的字符个数的空白位置,从而使得与其它行在视觉上达到了缩进的效果。 那么,canvas要想绘制出如css那样的首行缩进的文本样式效果,只需将X水平向右偏移相应的像素(pixel)即可。 内容过多以省略号结尾 无论是海报,还是书本的封面,总不肯多写几个字,倒像是一个惜字如命的家伙,生怕自己写多了,给自个儿带来了寿命减少几秒钟的担忧。那么,这时候,省略号这时候便闪亮登场了,很好地诠释着这一足够吸引用户眼球的重要任务。 而在canvas绘制文本时,只需判断是否绘制到文本的最后,若是,便在最后给原有文本追加上...即可。 自动换行 相对于首行缩进来讲,canvas要想实现文本自动换行,不单单只是计算X水平偏移量那么简单咯! 而还要计算Y纵向(垂直)偏移量,为了让你能够理解Y纵向偏移,我举个通俗的例子,我们平时不管是拿笔在纸上写字,还是在电子设备上敲击着文字,文本内容无不是由上而下、自上而下、从上而下的顺序呈现在我们的面前。由于纸或电子设备的宽度所限制,文本不得不另起一行,而这另起一行与之前的一行,就存在着纵向关系——另起一行是在之前的一行的下面(下方/ under),而之前的一行则就在另起一行的上方(上面 / upper)。 在实现自动换行这一效果时,我们应考虑到canvas该如何知道绘制当前在哪个位置(X水平位置)确需另起一行呢?这一点很重要,也是实现canvas自动换行的核心所在。 还是拿我们在纸张上写字或在电子设备上敲击文本时,我们知道换行(那是由于在纸张写的字大小差不多,一行只能容纳这么多文字)或电子设备设定好了字体大小,以此来推算出你写到哪个文字时,让你另起一行。 那么,canvas实现自动换行可以通过计算文字字体大小`及纵向(Y)偏移量的。 canvas提供了CanvasRenderingContext2D.measureText(text)这个API,它可以用来计算字符的宽度。 canvas 是以左上角为原点,也就是说,X轴 水平向右是`正数`,反之亦然;Y 轴纵向则是以向下为`正数`,反向则负。 要让canvas知道该在哪个位置自动换行,只需将文本的每个字符宽度进行累加,判断总字符宽度是否达到了canvas所设定的画布宽度,若是,则另起一行继续绘制剩余的文本字符,当然咯,在另起一行时,纵向 Y偏移量是要往下移动。
2024-08-03
[前端 建站]
其实,低成本甚至免费的,也是可以搭建个人网站的哦!
在日新月异的互联网浪潮下,想要搭建一个网站,已不再需要花费高昂的IDC 服务器费用以及人员维护等其他费用(相对于公有云来讲)。 身为一名IT、Coder(码农或程序员),对于搭建一个网站的过程,是在清楚不过的了。那就是搭建网站所需的三要素(三兄弟)——服务器、一套程序、域名。 云计算的崛起,致使越来越多的人上云体验了一把,与此同时,个人网站如雨后春笋般拔地而起,网站类型可谓是五花八门。(当然咯,云计算没出现之前,也是有人搭建个人网站,只是那高昂的IDC服务器,并不是每个人都愿意花那高昂的IDC服务器费)。 虽然云计算的云服务器对IDC服务器造成了巨大冲击,但摆在你我眼前的云服务器费用,着实不低啊!(国内各大云厂商为了抢占用户,不惜打起了价格仗,你我索性从中薅起了羊毛,虽然你我深知这羊毛终究是出自羊身上的)。 服务器(云服务器) 想要搭建一个网站,服务器(云服务器)是少不了的。毕竟网站也是程序编写出来的,而程序是需要编译 、运行的,很显然,服务器正扮演着运行这套网站程序的角色。 你我都知道,在云计算之前,想要搭建一个网站,光是租用IDC服务器的费用,就可能让你望而却步了。 可当云计算的到来,个人拥有一个网站,已不再是那么遥不可及(虽然,在这之前,个人也是可以搭建起网站的),毕竟,云服务器费用相比于IDC服务器费用不知便宜了多少(至少在搭建网站的预算降低),促使大多数人蜂拥而上云。 国内的云厂商,诸如,阿里云、腾讯云、华为云、京东云、百度云等(还有很多没列出来的小众云厂商),对新用户都有优惠活动(毕竟,他们为了抢用户,豁出去了),反之,老用户就享受不了那优惠活动了,虽然有吧!但显然优惠力度不是很大。 也正是由于国内各大云厂商领进新用户,而在该云厂商平台但凡购买了新用户优惠活动的云计算产品(如:云服务器)之后,你的身份自然而然地由新用户转变成老用户。可当你云服务器到期时(云服务器到期是指:云计算产品分 按时计费、按量计费,而云服务器是属于按时计费,它又细分为按月、按年),想要续费,那费用瞬间翻了好几倍啊!你一度怀疑,同等配置的云产品为什么在续费时会如此高昂呢?该不会是云厂商想要从新用户变为老用户身份的你,补足当初以优惠力度让入驻该云厂商平台的款项呢? 这也就是为什么,你常常点开一个个人网站(个人博客网站)时,不是出现了网站正在维护中……,便是该网站无法访问的情形。无非是数据迁移到新的服务器上去,或是不再为服务器续费,也不去其他新的云厂商购买云服务器了。 云服务器续费让人望而兴叹,纵使在其他云计算厂商以新用户的优惠价格买到了心仪的云服务器,将网站数据迁移到新服务器上,使得网站得以续命生存下去,虽然这不失为一种办法(薅云厂商的羊毛)。 但绝大多数人的做法是,云服务器到期了,便不再续费了(当然咯,这其中就包括 秋码记录),也没到新的云计算厂商购买新云服务器。而是去购买价格低廉的VPS(虚拟主机)。 由于VPS配置不高,空间不大等,在价格方面,足以碾压云服务器。故而成了很多站长的“首选”,从而解决了站长在云服务器续费与不续费之间、不续费与到其他云计算厂商购买新云服务器之间左右摇摆的困惑。(国内VPS有 帮瓦工……,国外倒是有很多,Hosting、freehost,还可以申请免费的VPS)。 虚拟主机的低配置、小空间,迫使了它只能运载些体量不是很大的网站程序(诸如个人博客、论坛、社区等)。 serverless 谈到serverless或许你会陌生,可一讲到github pages,想必你是知道的了。(github pages可以托管你的静态网站,如 秋码记录 )。 serverless相对于服务器而言,它便是无需服务器。 纵使github在国内访问速度不佳,也鲜有人去使用国内gitee pages(gitee.com提供的pages服务)、coding.net pages(腾讯旗下的代码托管平台)等,这其中的原因,不用我说,你自然也会懂得,这就好比,家楼下有生鲜超市,可你却不愿在那里买,宁愿去十公里外的大型商场买(这里包括但不限于顾客的口碑、以及以次充好等小伎俩,蒙骗顾客)。 网站程序 无论你是买了云服务器,还是选择了低廉的VPS,亦或是采用了serverless这种模式,搭建网站的程序你总该要有的吧(这时你迫不及待的大声嚷道:”谁说搭建网站,就非得需要程序了,一键云建站了解下,不但不需要什么网站程序,就连部署网站的运维人员也省了……“。这里我不禁打断你的话,指出了其中要害,”没错,一键云建站确实给你带来了便利,但你有没去考察过,使用云模板一键建站的都是些企业门户网站,个人博客、论坛、社区是不能用这个,第一,模板风格老套、重叠,第二,在费用方面觉不亚于云服务器“) 也不是说云模板建站有什么不好,可千篇一律的模板终将不适合来搭建个人博客、论坛、社区网站,虽说这些网站也在套用同一个程序,而使得网站又是千人一面,但他们却都不去使用云模板一键建站(其中缘由你该是懂得,若你不懂,执意要云模板一键建站,那就去试一试吧,也只有在试过了,你才会长大、明白)。或许你会问,”为什么你知道这些呢?你是不是使用过云模板一键建站呢?“在这里,我可以很肯定的对你说,”有些事情,并不是需要去试验才会明白的,而是靠理性的判断,以及绝大多数人为何不去使用它的思虑“。 即便网上充斥着大量的个人博客、论坛、社区等的开源程序,然而身为Coder(码农或程序员)的你,总是喜欢使用自己常用的编程语言(program language)从头开始编写,或是在开源程序的基础上进行二次开发,增加些自己独特的想法。 网站程序从头开始编写,不单单是Coder为了在他人面前炫技外,更重要的是Coder想把编程知识巩固起来。 而那些非Coder的外行人,是不会什么编程的,也就谈不上什么从头开始编写网站程序了,他们大多去找些既好看又开源的主题(theme)来构建自己的网站。 闻名于海内外的wordpress就是一个强大的开源程序,使用它可以任何形式的网站,如:电商网站、视频网站、企业门户、新闻网站、个人博客、论坛、社区等,主要还是取决于主题(theme)的搭配。 除了大名鼎鼎的wordpress外,还有国内的typecho、Zblog等,都是可以搭配主题(theme)。 无独有偶,秋码记录 则是使用海外知名的Hugo构建,而主题(theme)则是使用了开源的 Hugo-theme-kiwi ,托管于github pages上。 域名 其实,搭建一个网站,域名并不是必选项,那是因为可以使用ip进行访问,可一大推数字总没有 qiucode.cn 来的好记吧,这使得域名作为公网ip的别名而存在。 在上面讲诉了服务器、网站程序都有免费方案,那么域名是否也有呢?没错,域名也是有的,但都是些二级域名,诸如海外的js.org、eu.org等(如你网站想叫qiucode,那么免费二级域名便是qiucode.js.org`qiucode.eu.org`)。 国内免费的二级域名也是有的,同样也是很少人去使用的,正如serverless一样,人们宁愿去使用github pages,也不肯去国内那些serverless上。 也不是刻意的贬低国内这些互联网,而是他们的那些做法寒了人们的心。就拿百度搜索来说吧,先前我可是百度搜索的忠实用户啊!然而现在却再也不用百度搜索了,改用必应。(其中原有不细说,你总该是明白的)。 综上所诉,想要搭建一个网站,低成本甚至免费的方案都有的。 低成本方案一:虚主机(VPS) + 开源程序 + 免费的二级域名,费用用在了租用虚拟主机(VPS)上。 低成本方案二:虚拟主机(VPS)+ 开源程序 + 顶级域名,费用花在了虚拟主机(VPS)和购买域名上。 低成本方案三: serverless + 开源程序 + 顶级域名,费用花在了购买顶级域名上(秋码记录 就是选用这个方案)。
2024-07-26
[建站]
腾讯云COS托管静态网站,以及如何解决访问出现了下载网页的情况
腾讯云对象存储(Cloud Object Storage,简称COS),与其他云厂商所提供的云对象存储都是面向非结构化数据,只是每个云厂商的叫法有别于他家,或许是更能彰显厂商的品牌吧! 但不管云厂商怎么给云对象存储起名,最终客户关心的还是性价比。 使用云对象存储,无非是存放些静态资源(javascript 第三方库、项目中内部的javascript文件、样式文件css、字体文件、小图标等),以此来减轻服务器所承载的压力,从而使得整个站点让用户体验效果显著提升了。 然而,本文要讲的是,怎么样在云对象存储中托管静态网站(这虽然听起来有点可笑,这年头,谁还玩静态网站啊。你也别笑,秋码记录 就是一个很好的静态网站的例子,它也的确是静态网站,可它却具有了与用户交流的文章评论`功能!) 当然咯,云对象存储用来托管静态网站,也只是在开发、测试阶段,毕竟大流量的情况下,费用那是不可估量的! 创建存储捅 对于存储捅这个名词,刚刚说了,每个云厂商的叫法不同而已。 首先,进入腾讯云-》控制台(在这之前,你当然得购买了腾讯云 COS),创建存储捅,名称随便填写,在访问权限选择公共读私有写。 而后,服务端加密这一项,选择SSE-COS(看着名称,估计是腾讯云又仿造他人什么的吧!) 就这样,腾讯云COS就创建成功了,之后便可以上传你的静态资源到这个对象捅里了。 配置静态网站 既然,我们使用COS来托管静态网站,那么是少不了些必要的配置,比如开启静态网站`开关等等。 在左侧导航栏中找到基础配置,随后在其子项的静态网站开启静态网站的配置。(感觉在绕口令似的,其实,不关你是这么觉,我也这么觉得。) 绑定自定义域名 同样的,还是在左侧导航栏,找到域名与传输管理这一泪目,点开它底下的自项,点击自定义绑定域名。 在绑定自定义域名之前,你得先确认你刚购买的COS区域是国内的,还是非国内的,若是国内区域的COS,那么你绑定自定义域名时,这个自定义域名是需要备案的。当然咯,COS购买时选择的是香港区域,自定义域名是不需要备案的哦! 浏览器访问托管的静态网站却下载了文件 很不辛,在你配置了存储捅的静态网站,上传了所有的静态资源后,兴致勃勃地打开浏览器,你以为页面能够如期的展示你所希望的样子,然而,历史性的一刻,让你瞬间愕然,这是怎么回事呢?怎么就直接下载了页面文件(也就是下载当前的index.html`文件)?这到底是哪个环节出了问题? 然而,你是按着官方文档来着,并且文档上也是这么做的,中间也没有遗漏些什么重要配置啊!(关键是也没什么重要配置,充其量就是开启了静态网站的开关)。 于是,你借助搜索引擎的强大搜寻功能,找找看,到底有没有解决办法(也就是别人在COS托管静态网站时,对于访问时出现下载文件`是怎么处理的)。 不搜不知道,一搜可谓是天下知。使用COS(也有其他云厂商的)托管静态网站的博文、帖子、论坛还真不少,你点开一看,他们与你的静态网站配置如出一辙,他们也同样出现了你所出现的问题(没把你绕进去吧,也就是他们跟你一样,在浏览器访问也出现了下载index.html文件。) 最终,解决办法便是在刚刚上传的index.html,点击右上角的...,在上弹出的列表项中,再次点击自定义头部 当你看到这个对话框,你或许就该恍然大悟了,也总算明白了,为什么浏览器访问会出现下载 index.html的情况了吧!毕竟,腾讯云默认将你上传的文件头部定义为text/html。 我们点击编辑来修改这个index.html文件表头。 在参数选择下拉框中选中Content-Disposition,值是手动输入inline. 现在,你再次打开浏览器进行访问,这回,展现在你眼前的,便是你所期望的页面展示了。 可当你回过头,再去查看index.html头部信息时,却发现它自动的加上初始的那个Header信息,这时,你不禁啐了一口,“腾讯云,真TMD恶心,哦!不,国内的这些云厂商都TMD超恶心”。 当然咯,不管是腾讯云COS,还是其他国内云厂商,想要使用云对象存储来托管静态网站还是比较,怎么说呢!用来开发、测试勉强还凑合吧!
2024-07-19
[云计算]
错误分析 (Machine Learning 研习十九)
错误分析 您将探索数据准备选项,尝试多个模型,筛选出最佳模型,使用 Grid SearchCV微调其超参数,并尽可能实现自动化。在此,我们假设您已经找到了一个有前途的模型,并希望找到改进它的方法。其中一种方法就是分析它所犯的错误类型。 首先,查看混淆矩阵。为此,首先需要使用 cross_val_predict() 函数进行预测;然后可以像之前一样,将标签和预测值传递给 confusion_matrix()函数。不过,由于现在有 10 个类别而不是 2 个,混淆矩阵将包含大量数字,可能难以读取。 混淆矩阵的彩色图更容易分析。要绘制这样的图表,请使用ConfusionMatrixDisplay.from_predictions() 函数,如下所示: from sklearn.metrics import ConfusionMatrixDisplay y_train_pred = cross_val_predict(sgd_clf, X_train_scaled, y_train, cv=3) ConfusionMatrixDisplay.from_predictions(y_train, y_train_pred) plt.show() 这就产生了 图1 中的左图。这个混淆矩阵看起来相当不错:大多数图像都在主对角线上,这意味着它们被正确分类了。请注意,对角线上第 5 行第 5 列的单元格看起来比其他数字略暗。这可能是因为模型对 5 的错误较多,也可能是因为数据集中 5 的数量比其他数字少。这就是为什么要对混淆矩阵进行归一化处理,将每个值除以相应(真实)类别中的图像总数(即除以行的总和)。只需设置 normalize="true "即可。我们还可以指定 val ues_format=".0%"参数来显示不带小数点的百分比。下面的代码将生成 图1 右侧的图表: ConfusionMatrixDisplay.from_predictions(y_train, y_train_pred, normalize="true", values_format=".0%") plt.show() 现在我们不难发现,只有 82% 的 5 图像被正确分类。模型在处理 5 的图像时最常见的错误是将其误判为 8:在所有 5 的图像中,有 10%的图像被误判为 8。但只有 2% 的 8 被误判为 5;混淆矩阵通常不是对称的!如果你仔细观察,就会发现很多数字都被错误地分类为 8,但从这张图上并不能一眼看出。如果想让错误更明显,可以尝试将正确预测的权重设为零。下面的代码就是这样做的,并生成了图2 左侧的图表: sample_weight = (y_train_pred !
2024-04-10
[Machine Learning 人工智能]
多类别分类器(Machine Learning 研习十八)
多类别分类器 二元分类器可以区分两个类别,而多类别分类器(也称为多叉分类器)可以区分两个以上的类别。 一些 Scikit-Learn 分类器(如 LogisticRegression、RandomForestClassifier 和 GaussianNB)能够原生处理多个类别。其他分类器则是严格的二进制分类器(如 SGDClassifier 和 SVC)。不过,您可以使用多种策略来使用多个二进制分类器执行多类分类。 要创建一个能将数字图像分为 10 类(从 0 到 9)的系统,一种方法是训练 10 个二进制分类器,每个数字一个(0-检测器、1-检测器、2-检测器,以此类推)。然后,当您想对一幅图像进行分类时,您可以从每个分类器中得到该图像的判定分数,然后选择分类器输出分数最高的类别。这就是所谓的 “以一敌百”(OvR)策略,有时也称为 “以一敌众”(OvA)策略。 另一种策略是为每一对数字训练一个二元分类器:一个用于区分 0 和 1,另一个用于区分 0 和 2,还有一个用于区分 1 和 2,以此类推。这就是所谓的一对一(OvO)策略。如果有 N 个类别,则需要训练 N × (N - 1) / 2 个分类器。对于 MNIST 问题,这意味着要训练 45 个二进制分类器!当你想对一幅图像进行分类时,你必须让图像通过所有 45 个分类器,看看哪个分类器赢得了最多的对决。OvO 的主要优势在于,每个分类器只需在训练集中包含其必须区分的两个类别的部分进行训练。 有些算法(如支持向量机分类器)随训练集的大小而缩放,效果不佳。对于这些算法,OvO 是首选,因为在小训练集上训练多个分类器比在大训练集上训练少数分类器更快。不过,对于大多数二元分类算法来说,OvR 是首选。 Scikit-Learn 会检测你是否尝试在多分类任务中使用二元分类算法,并根据算法自动运行 OvR 或 OvO。让我们使用 sklearn.svm.SVC 类支持向量机分类器来尝试一下。我们只对前 2,000 张图像进行训练,否则会耗费很长时间: from sklearn.svm import SVC svm_clf = SVC(random_state=42) svm_clf.fit(X_train[:2000], y_train[:2000]) # y_train, not y_train_5 我们使用从 0 到 9 的原始目标类别(y_train),而不是 5 对其余目标类别(y_train_5)来训练 SVC。由于有 10 个类别(即多于 2 个),Scikit-Learn 使用 OvO 策略训练了 45 个二元分类器。现在,让我们对一幅图像进行预测:
2024-04-03
[Machine Learning 人工智能]
使用CSS计数器,在目录名称前加上了序号,让目录看起来更加井然有序
目录(Text of Contents缩写为TOC),其实就是一篇文章的概要或简述。这好比,去书店买书,先是被这本书的标题所吸引,而后我们才会,翻开这本书目录,看看这本书主要是在讲些什么?我们在看目录的同时,脑中也在不停的思衬,”这本书到底值不值得买呢?但是没有什么实战内容耶!“ 文章目录 其实,一篇文章也不非要目录的,只要段落分的好,就算是长篇大论也是无关紧要的! 只是文章有了目录,让人一眼就能瞧出这篇文章到底讲了什么?虽然标题上有说,但还是得为哪几个段落起个副标题。 再说了,文章目录可以让用户在页面上,点击到达指定目录名称下进行浏览。虽然这在很大层度上是可以通过鼠标滑动,滚动到想要浏览的位置。 Hugo-theme-kiwi开源博客主题已然有了文章目录这一功能,也就是 秋码记录 站点正在使用的博客主题(由于 秋码记录 托管于 Github.com Pages,故而国内的友人在访问时,比较缓慢,甚至有时可能出现无法打开该网站)。 对目录名称前添加序号,我们首先想到的当然是使用Hugo模板渲染去实现。 序号,顾名思义,就是有顺序的号码,通俗来讲,便是1、,2、,3、,4、,……。可在Hugo模板渲染中使用计数器来实现。 css计数器 或许也只有在使用了CSS 计数器后,你就会摒弃代码中使用Hugo模板渲染的那部分又长又拖代码了。 在CSS计数器中,counter-reset和counter-increment属性是必不可少的。counter-reset在每次新的列表开始时重置计数器,而counter-increment在每个列表项上增加计数器。 需要注意的是:counter-reset 是需要计数的父标签上的! 那么,就将 counter-reset设置在ol标签上即可,即便是某一项有子目录,那也还是在ol标签内的! .toc-content ol{ list-style-type: none; counter-reset: item } 现在,我们就可以对目录名称设置伪选择器了。 在编写CSS样式之前,有必要说下counters()函数,在CSS中,它返回一个计数器的列表值,这个列表可以包含一个或者多个嵌套的计数器。 函数counters()有两个参数: 第一个参数是你要访问的计数器的名称,在你的例子中,该名称就是 item。 第二个参数是字符串,用来分隔计数器的各个级别。在你的例子中,这个分隔符是英文的句点 . .toc-content ol li a:first-of-type::before{ counter-increment: item; content: counters(item,".")"、"; font-weight: 700; margin-right: 1px; } 比如在多级嵌套的列表中,如果在第一级的第二个项中的第三个小项,那么 counters() 的值就会是 2.3、。 字符串、 紧接着 counters(item, ".") 的作用是将结果后面添加一个顿号,使其格式化输出更美观。 所以 counters(item, ".") ". " 的作用就是生成并显示一个根据当前嵌套列表项的层级和序号构成的数字序列,每一级数字之间用句点分隔,并在最后跟着一个顿号。例如输出1、,2.1、,2.2、,等等。 最终效果可查看秋码记录文章详情页,右侧侧边栏目录。
2024-04-01
[前端]
使用 golang 以及 Gin 框架,将上传的图片在不保存至本地的情况下添加水印,并上传至阿里云 OSS
正如标题所述,使用golang对上传图片添加水印,以及将图片上传到阿里云OSS,网上一搜索,便有你想要的结果了,可是,他们却先将上传图片添加水印后保存在本地,而后再将添加了水印的图片上传到阿里云OSS。 这无疑是暂时占用了你电脑的磁盘空间(这里说是暂时,因为你可以通过程序对上传到阿里云OSS成功的图片进行删除),即便是这样,它也是消耗了磁盘读写操作,虽然人类是察觉不到这么细微的变化。 然而,作为技术人员的我们(不介意我这么称呼自己吧!),使能够Review出这段程序的问题。很显然,本地图片是要通过程序处理,添加水印,而后最终储存到阿里云OSS中,而不是又要在本地多存了一张比原图多了些水印的图片。 图像处理库 既然我们的目的明确了,那么就卷起柚子加油干吧! 虽然,使用golang对上传图片添加水印,以及如何将图片上传到阿里云OSS中,是两个独立分开的。但是,这两步看似分而食之的程序,其实是可以合二为一的!(我想,正在浏览本文的你,也是这么想的!) 这是可行的方案,毕竟先前的秋码记录 就是这么做的(那是使用Java构建的那些年!当然现在的 秋码记录 改用 ```Hugo·``搭建了)。 既然,java能实现对上传图片添加水印,而不暂时保存在本地,立马即可上传到阿里云OSS中。想必,golang也是可以完成的! 然而,网上相关的资料有限,才能铸就本文的诞生! 首先,我是用golang的版本是1.19,虽然不是最新的,但却不妨碍我们继续对本文的讲解。 虽然,人类总是对新鲜事物充满好奇,从而萌生了猎奇心。但也只有在旧事物的烘衬下,人们才能对新事物寄以最大的希望!这就好比,老婆总是别人的好看(当然,别人的老婆也有没有自己老婆好看的),这才造就了黄脸婆这一全国男人在没有老婆在身旁统一叹息声! 你得在你电脑任一磁盘下,新建一空文件夹,随后打开黑窗口(Terminal),输入以下命令,说明是modules进行管理的(毕竟我使用的是golang 1.19): go mod init qiucode.cn/uploadImage 对于以上这行命令,就是初始化golang模块(module),在golang的世界是```万物皆可模块``(我说的如果不对,那么说出你的想法)。 初始化项目后,我们会发现文件夹下多了个go.mod文件(这个就是用来管理第三方依赖库的管理文件,不需要操作!),在该同级目录下新建main.go文件。 既然本文是探讨如何实现图片添加水印的,那么引入图像库那是必不可少的! go get github.com/fogleman/gg 本文不会对这个图像库进行深层次的讲解!毕竟本文的核心内容是介绍如何对图片添加水印,而不是避重就轻、本末倒置讲起了本该一笔带过的东西,却花了浓墨重彩去着重的描绘刻画它,到头来,却失了初心,乱了本文的主旨,实属不该。(实在不清楚的,可以去查看其文档) 很显然,将图片上传到阿里云OSS上,引入其SDK,那是必不可少的(关于这一点,应该不需要我多费口舌了吧) go get github.com/aliyun/aliyun-oss-go-sdk/oss 接下来的这个依赖库,并不是必须的(那就是可选的),毕竟,有它没有它,本文都可以实现! go get github.com/gin-gonic/gin 是啊!都说了,不引入它,本文也可以实现,那么我为什么还引入了呢?(关于这一点,欢迎你能在评论中留下你的只言片语,请不要吝啬你的文字!) 用代码实现标题的需求 前提准备工作就绪,我们该正式进入编码环节了。到了这里,正处于屏幕前的你,想必早就迫不及待了吧!毕竟,你就是与我有同样的需求,才会浏览本文的(当然也有那种,鼠标不小心点到了,但那种几率是很小的,我相信你不是属于那一类的) 首先,我们使用VS Code(你也可以使用其他你平时常用的IDE,不必非要使用与我一样的VS Code,然而,作为一款开源免费的IDE,你还有什么理由不去使用它呢?哦,差点忘记了,都说了,使用IDE是个人的自由,可我这么一说,倒有了让你使用VS Code之嫌。虽然,或许你比较喜欢使用收费软件,但你都是找的破解方法来破解软件,从而使用它们) 打开刚刚新建的main.go文件,开始逐步实现标题的需求。 package main import ( "bytes" "image" "image/png" // "image/jepg" //用于对 jpg 格式的图片进行处理 本文暂时不对 jpg 图片做处理 "github.com/gin-gonic/gin" //web 框架 "github.com/fogleman/gg" // 图像处理哭 "github.com/aliyun/aliyun-oss-go-sdk/oss" //阿里云OSS SDK ) 随后,我们在main函数中实现标题中的需求。
2024-03-30
[golang gin]
绘制特征曲线-ROC(Machine Learning 研习十七)
接收者操作特征曲线(ROC)是二元分类器的另一个常用工具。它与精确度/召回率曲线非常相似,但 ROC 曲线不是绘制精确度与召回率的关系曲线,而是绘制真阳性率(召回率的另一个名称)与假阳性率(FPR)的关系曲线。FPR(也称 “下降率”)是阴性实例被错误归类为阳性实例的比率。它等于 1 - 真阴性率 (TNR),即正确分类为阴性的阴性实例的比率。TNR 也称为特异性。因此,ROC 曲线是灵敏度(召回率)与 1 - 特异性的关系图 要绘制 ROC 曲线,首先要使用 roc_curve() 函数计算不同阈值的 TPR 和 FPR: from sklearn.metrics import roc_curve fpr, tpr, thresholds = roc_curve(y_train_5, y_scores) 然后可以使用 Matplotlib 绘制 FPR 与 TPR 的对比图。下面的代码可以绘制出 见下图 所示的图形。要找到与 90% 精度相对应的点,我们需要查找所需阈值的索引。由于在这种情况下阈值是按递减顺序排列的,因此我们在第一行使用 <= 而不是 >=: idx_for_threshold_at_90 = (thresholds <= threshold_for_90_precision).argmax() tpr_90, fpr_90 = tpr[idx_for_threshold_at_90], fpr[idx_for_threshold_at_90] plt.plot(fpr, tpr, linewidth=2, label="ROC curve") plt.plot([0, 1], [0, 1], 'k:', label="Random classifier's ROC curve") plt.plot([fpr_90], [tpr_90], "ko", label="Threshold for 90% precision") [.
2024-03-29
[Machine Learning 人工智能]
网站引入 Prism,使得代码高亮显示,并一键复制代码块
曾几何时,苦恼如何将本地写好的博文,更好的展示读者屏幕前?若只是简简单单的文章,其实还是很好的解决它的!可是,像我们这样写技术文章(有点牵强)的,在文章内容嵌入部分代码是在所难免的。 然而,由于没能将代码与文本区分开来,致使两者混在一起,分不出彼此。由此给读者带来了视觉上得不适,它并没有很好的像代码编辑器那样高亮。 下载 Prism 虽然市面上能让代码块高亮显示,远不止Prism这一款,而我又为什么选择这一款呢?这的确是个好问题,然而我只能回答您的是,它功能比较强大吧!(或许您还不能信服),这就好比是情人眼里出西施,您的老婆/老公或女朋友/男朋友长得不是那么美/那么帅(或许您在某一瞬间也是这么觉得),但是,您不还是选择了她/他吗?即便是,您和伴侣在逛街时,迎面走来一位身材高挑的美女/帅哥,想必您的伴侣是在您不经意间,偷瞄了一眼。 进入prism官网下载: https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript 随后,我们在项目中引入Prism.css样式文件。 <link href="themes/prism.css" rel="stylesheet" /> 以及Prism.js文件。 <script src="prism.js"></script> 当然咯,您的代码块是需要使用<pre>和<code class="language-*"标签。 <pre><code class="language-html"> <link href="themes/prism.css" rel="stylesheet" /> </code></pre> 添加 clipboard 复制代码按钮 若是有一点按钮就可以复制这段代码,想必应该是没有人会再去用鼠标去滑动选择代码,然后右键,选择复制选项,或者直接按住键盘上的Ctrl + C。 首先,想要在项目中添加clipboard功能,那么,就显得下载它,这是毋庸置疑的! 当然,我们还是到Prism官网下载它, 在项目中引入: <script src="plugins/clipboard.js"></script> Hugo-theme-kiwi 中引入 Prism 首先,我们在Hugo-theme-kiwi主题的head.html文件引入blackmac.css样式文件。 <link rel="stylesheet" href="{{ .Site.BaseURL }}css/blackmac.css"> blackmac.css文件内容如下: code[class*="language-"],pre[class*="language-"]{color:#f8f8f2;background:#313238;text-shadow:0 1px rgba(0,0,0,.3);font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:2;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;}pre[class*="language-"]{padding:.5em;margin:.5em 0;overflow:auto;}:not(pre)>code[class*="language-"],pre[class*="language-"]{background:#21252a}:not(pre)>code[class*="language-"]{padding:.1em;border-radius:.3em;white-space:normal}.token.comment,.token.block-comment,.token.prolog,.token.doctype,.token.cdata{color:#999;}.token.punctuation{color:#ccc;}.token.tag,.token.attr-name,.token.namespace,.token.deleted{color:#e2777a;}.token.function-name{color:#6196cc;}.token.boolean,.token.number,.token.function{color:#f08d49;}.token.property,.token.class-name,.token.constant,.token.symbol{color:#f8c555;}.token.selector,.token.important,.token.atrule,.token.keyword,.token.builtin{color:#cc99cd;}.token.string,.token.char,.token.attr-value,.token.regex,.token.variable{color:#7ec699;}.token.operator,.token.entity,.token.url{color:#67cdcc;}.token.important,.token.bold{font-weight:bold;}.token.italic{font-style:italic;}.token.entity{cursor:help;}.token.inserted{color:green;}pre.line-numbers{padding-bottom:.8em;padding-left:3.3em;counter-reset:linenumber}pre.line-numbers>code{white-space:inherit font-size:15px}.line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:3em;font-size:100%;left:-0.1em;width:3em;letter-spacing:-1px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.line-numbers-rows>span{pointer-events:none;display:block;counter-increment:linenumber}.line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.9em;text-align:right;background:#272c33}div.code-toolbar{font-size:100%;border-radius:4px;position:relative;box-shadow:0 0 20px 5px rgba(0,0,0,.4);padding-top:30px;background-color:#161616;margin:20px 0 20px 0}.code-toolbar:before{content:" ";position:absolute;-webkit-border-radius:50%;border-radius:50%;background:#fc625d;width:11px;height:11px;left:10px;top:10px;-webkit-box-shadow:20px 0 #fdbc40,40px 0 #35cd4b;box-shadow:20px 0 #fdbc40,40px 0 #35cd4b;z-index:2}div.code-toolbar>.toolbar{padding-right:.4em;position:absolute;top:.09em;right:.2em;width:100%;text-align:center;}div.code-toolbar:hover>.toolbar{opacity:1}div.code-toolbar>.toolbar .
2024-03-23
[前端]
精确率(召回率)的权衡(Machine Learning 研习十六)
精确率(召回率)的权衡 为了理解这种权衡,让我们看看 SGDClassifier 如何做出分类决策。 对于每个实例,它根据决策函数计算分数。 如果该分数大于阈值,则将该实例分配给正类; 否则它会将其分配给负类。 图 3-4 显示了从左侧最低分数到右侧最高分数的几个数字。 假设决策阈值位于中心箭头(两个 5 之间):您会在该阈值右侧发现 4 个真阳性(实际为 5),以及 1 个假阳性(实际上为 6)。 因此,使用该阈值,精度为 80%(5 分之 4)。 但在 6 个实际的 5 中,分类器仅检测到 4 个,因此召回率为 67%(6 中的 4)。 如果提高阈值(将其移动到右侧的箭头),假阳性(6)会变成真阴性,从而提高精度(在本例中高达 100%),但一个真阳性会变成假阴性 ,将召回率降低至 50%。 相反,降低阈值会增加召回率并降低精确度。 Scikit-Learn 不允许您直接设置阈值,但它允许您访问它用于进行预测的决策分数。 您可以调用其decision_function()方法,而不是调用分类器的predict()方法,该方法返回每个实例的分数,然后使用您想要根据这些分数进行预测的任何阈值: SGDClassifier 使用等于 0 的阈值,因此前面的代码返回与 Predict() 方法相同的结果(即 True)。 让我们提高门槛: 这证实了提高阈值会降低召回率。 该图像实际上代表的是 5,当阈值为 0 时分类器会检测到它,但当阈值增加到 3,000 时分类器会错过它。 y_scores = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3, method="decision_function") 有了这些分数,使用 precision_recall_curve() 函数计算所有可能阈值的精度和召回率(该函数添加最后精度 0 和最后召回率 1,对应于无限阈值): from sklearn.
2024-03-21
[Machine Learning 人工智能]
1
2
3
4
...
15