Hexo Next 博客添加相册瀑布流
原文:https://rebootcat.com/2020/09/19/nextphotowall/
前言
一直没有时间来整理下博客搭建的一些事情,现在补上一篇,给 Hexo Next 博客添加一个相册功能,使用瀑布流的方式。
原理说明
- 使用 github 作为仓库存储图片文件(图床)
- 使用 jsdelivr 进行图片 CDN 加速
优点
此种方式的优点是免费,不需要购买其他的对象存储产品;并且使用的是 github 作为图床,图片不会丢失。
早期的博文使用的是七牛云的免费存储,结果后来被他们删掉了。。。结果造成文中的一些图片链接都是 404,有兴趣的可以翻一翻我早期的博客。
缺点
由于采用的是 github 仓库存储图片,但是 github 对单仓库有 50MB 的大小限制,所以单仓库可能不能够存储太多的文件;
解决方法就是建立很多的图片仓库(稍微有点费劲,不过是行得通的);另外上传的单张图片大小最好不要太大。
还有个缺点就是得折腾啊,且看我后文。
各位可以参考下我的相册瀑布流: 摄影
开始搭建相册瀑布流
开始之前,需要简单介绍一下,我参考的是 Hexo NexT 博客增加瀑布流相册页面 这篇文章,文中涉及到的脚本主要都是 js 实现;与他不同的是,由于我对 js 的掌握远远不及我对 Python 的掌握,故部分脚本我采用了 Python 实现。
所以在开始操作之前,你可以根据自己的技能,选择不同的方式。如果你擅长 python,那么跟着我来吧。
新建 photo 页面
去到博客根目录:
mkdir -p source/photos
然后进入 photos 目录:
cd source/photos
vim index.md
把下面的粘贴保存:
---
title: 摄影
type: photos
---<!-- CSS Code -->
<style>
.MyGrid{width:100%;max-width:1040px;margin:0 auto;text-align:center}.card{overflow:hidden;transition:.3s ease-in-out;border-radius:8px;background-color:#efefef;padding:1.4px}.ImageInCard img{padding:0;border-radius:8px}
@media(prefers-color-scheme:dark){.card{background-color:#333;}}
</style>
<!-- CSS Code End --><div class="MyGrid"></div>
修改 Next 主题配置文件
添加了 photos 页面后,需要在 next 配置文件中修改:
vim themes/next/_config.yml
找到 menu 项,填入如下:
photos: /photos || fas fa-camera-retro
比如我的是这样的:
menu:home: / || homeabout: /about/ || usertags: /tags/ || tagscategories: /categories/ || tharchives: /archives/ || archive#schedule: /schedule/ || calendar#sitemap: /sitemap.xml || sitemap#commonweal: /404/ || heartbeatguestbook: /guestbook || fas fa-commentsphotos: /photos || fas fa-camera-retrowiki: /wiki/ || wikipedia-w
完成之后还需要修改一下这个文件:
vim themes/next/languages/zh-CN.yml
找到 menu 项,加入如下一行:
photos: 摄影
比如我的是这样的:
menu:home: 首页archives: 归档categories: 分类tags: 标签about: 关于search: 搜索schedule: 日程表sitemap: 站点地图commonweal: 公益 404guestbook: 留言photos: 摄影wiki: 维基
OK,到这里应该能看到这个 摄影 页面了,你可以现在本地测试一下看:
hexo s -g
添加 js 脚本
首先需要在 source 目录下新建一个 js 目录,用来保存自定义的一些 js 脚本;
mkdir -p source/js
然后新建 mygrid.js 文件,粘贴下面的一段代码:
// 获取网页不含域名的路径
var windowPath = window.location.pathname;
// 图片信息文件路径
var imgDataPath = '/photos/photoslist.json';
// 图片显示数量
var imgMaxNum = 50;
// 获取窗口宽度(以确定图片显示宽度)
var windowWidth = window.innerWidth
|| document.documentElement.clientWidth
|| document.body.clientWidth;
if (windowWidth < 768) {var imageWidth = 145; // 图片显示宽度(手机)
} else {var imageWidth = 215; // 图片显示宽度
}
// 腾讯云图片处理样式(根据图片显示宽度)
var imgStyle = '!' + imageWidth + 'x';// 图片卡片(照片页面)
if (windowPath.indexOf('photos') > 0 ) {var LinkDataPath = imgDataPath;photo = {page: 1,offset: imgMaxNum,init: function () {var that = this;$.getJSON(LinkDataPath, function (data) {that.render(that.page, data);});},render: function (page, data) {var begin = (page - 1) * this.offset;var end = page * this.offset;if (begin >= data.length) return;var html, imgNameWithPattern, imgName, imageSize, imageX, imageY, li = "";for (var i = begin; i < end && i < data.length; i++) {imgNameWithPattern = data[i].split(';')[1]; // a.pngimgName = imgNameWithPattern.split('.')[0] // aimageSize = data[i].split(';')[0]; // length.heightimageX = imageSize.split('.')[0]; // lengthimageY = imageSize.split('.')[1]; // heightcdn_url = data[i].split(';')[2]; // 原图 cdn urlsmall_cdn_url = data[i].split(';')[3]; // 缩略图 cdn urlli += '<div class="card" style="width:' + imageWidth + 'px" >' +'<div class="ImageInCard" style="height:'+ imageWidth * imageY / imageX + 'px">' +'<a data-fancybox="gallery" href="' + cdn_url + '" data-caption="' + imgName + '" title="' + imgName + '">' +'<img data-src="' + small_cdn_url + '" src="' + small_cdn_url + '" data-loaded="true">' +'</a>' +'</div>' +'</div>'}$(".MyGrid").append(li);this.minigrid();},minigrid: function() {var grid = new Minigrid({container: '.MyGrid',item: '.card',gutter: 12});grid.mount();$(window).resize(function() {grid.mount();});}}photo.init();
}
或者你可以直接在我的博客上找到: rebootcat.com/mygrid.js
wget https://rebootcat.com/js/mygrid.js -O source/js/mygrid.js
新建图片信息文件
我们再次回到 photos 目录,创建文件 photoslist.json:
vim source/photos/photoslist.json
然后输入如下的内容:
["1080.1920;WechatIMG114.jpeg;https://cdn.jsdelivr.net/gh/smaugx/MyblogImgHosting/rebootcat/photowall/cat/WechatIMG114.jpeg;https://cdn.jsdelivr.net/gh/smaugx/MyblogImgHosting/rebootcat/photowall/cat/WechatIMG114_small.jpeg","3024.4032;WechatIMG25834.jpeg;https://cdn.jsdelivr.net/gh/smaugx/MyblogImgHosting/rebootcat/photowall/cat/WechatIMG25834.jpeg;https://cdn.jsdelivr.net/gh/smaugx/MyblogImgHosting/rebootcat/photowall/cat/WechatIMG25834_small.jpeg"
]
OK, 到现在应该你能从博客上看到这两张图片了:
hexo s -g
本地测试一下,如果你能看到在博客的 摄影 页面看到这两张图片,那么说明你的配置没问题,你可以进行接下来的操作了;如果你不能正确显示,说明前面的步骤出了问题,自己研究调试一下;如果你还不能解决,欢迎联系我。
使用 python 脚本生成 photoslist.json
上面可以看到,photoslist.json 存放的是图片的信息,mygrid.js 解析 photoslist.json 这个文件,然后在 photos 页面添加 dom.
所以核心的部分在于 photoslist.json 文件,我们可以分析下这个文件:
1080.1920;WechatIMG114.jpeg;https://cdn.jsdelivr.net/gh/smaugx/MyblogImgHosting/rebootcat/photowall/cat/WechatIMG114.jpeg;https://cdn.jsdelivr.net/gh/smaugx/MyblogImgHosting/rebootcat/photowall/cat/WechatIMG114_small.jpeg
photoslist.json 保存的是一个 list,list 中每一行是一张图片的信息,包括原始图片大小、文件名、原始图片cdn链接、缩略图cdn链接。
前面已经提到,我们的图片是使用了 github 作为图床(仓库),然后使用 jsdelivr 进行 cdn 加速。所以我们应该准备好图片文件,然后上传到仓库。
新建 github 仓库,用来存放图片文件
在 https://github.com 上创建图片仓库。
当仓库容量超过 50MB 之后需要重新再新建一个仓库
本地克隆仓库,然后把图片放入仓库,上传(这里以我的仓库为例)
git clone git@github.com:smaugx/MyblogImgHosting_2.git blogimg_2
cd blogimg_2# put some image in this dir...
git push
生成 photoslist.json 文件
编写 python 脚本或者直接从我的网站下载:
wget https://rebootcat.com/js/phototool.py -O phototool.py
脚本如下:
#!/usr/bin/env python
# -*- coding:utf8 -*-import os
import glob
from PIL import Image, ExifTags
import jsonconfig = {# github 存储图片的仓库(本地仓库基准目录)'github_img_host_base': '/Users/smaug/blogimg_2',# 会对这个目录下的所有文件夹进行遍历,相同目录生成_samll 的 缩略图'img_path': '/Users/smaug/blogimg_2/rebootcat/photowall',# cdn 前缀'cdn_url_prefix': 'https://cdn.jsdelivr.net/gh/smaugx/MyblogImgHosting_2',# hexo 博客存放 photos 信息的 json 文件'photo_info_json': '/Users/smaug/blog_rebootcat/source/photos/photoslist.json',}# 压缩图片到 90%(目的是为了移除一些gps 等信息,并非真的为了压缩)
def compress_img(img_path, rate = 0.99, override = False):support_ftype_list = ['png', 'PNG', 'jpeg', 'JPEG', 'gif', 'GIF', 'bmp']sp_img = img_path.split('.')if not sp_img or sp_img[-1] not in support_ftype_list:print("not support image type:{0}", img_path)return Falsesp_img = img_path.split('/')if not sp_img:print("please give the right image path:{0}", img_path)return Falseimg_full_name = sp_img[-1]img_name = img_full_name.split('.')[0]img_type = img_full_name.split('.')[1]img_path_prefix = img_path[:-len(img_full_name)]# 覆盖原图或者另存为compress_img_path = ''if override:compress_img_path = img_pathelse:compress_img_path = '{0}{1}_com.{2}'.format(img_path_prefix, img_name, img_type)img = Image.open(img_path)try:for orientation in ExifTags.TAGS.keys() :if ExifTags.TAGS[orientation]=='Orientation' : breakexif=dict(img._getexif().items())if exif[orientation] == 3 :img=img.rotate(180, expand = True)elif exif[orientation] == 6 :img=img.rotate(270, expand = True)elif exif[orientation] == 8 :img=img.rotate(90, expand = True)except Exception as e:print("catch exception:{0}",e)try:original_size = img.sizelength = original_size[0]height = original_size[1]new_length = int(length * rate)new_height = int(height * rate)print("originla length:{0} height:{1}", length, height)print("after compress length:{0} height:{1}", new_length, new_height)img = img.resize((new_length, new_height), Image.ANTIALIAS)img.save(compress_img_path, img_type)print("save compress img {0}".format(compress_img_path))return Trueexcept Exception as e:print("catch exception:{0}",e)return False# 对 img_path 目录下的文件夹递归生成缩略图保存到同目录下
def thumbnail_pic(github_img_host_base, img_path, cdn_url_prefix):# 删除最后一个 '/'if img_path[-1] == '/':img_path = img_path[:-1]if github_img_host_base[-1] == '/':github_img_host_base = github_img_host_base[:-1]if cdn_url_prefix[-1] == '/':cdn_url_prefix = cdn_url_prefix[:-1]photo_info_list = []for item in os.listdir(img_path):print(item)abs_item = os.path.join(img_path, item)if os.path.isdir(abs_item): # sub-dirsub_img_path = abs_itemprint("cd dir:{0}".format(sub_img_path))sub_photo_info_list = thumbnail_pic(github_img_host_base, sub_img_path, cdn_url_prefix)photo_info_list.extend(sub_photo_info_list)else: # fileftype = item.split('.')if not ftype or len(ftype) != 2:print("error: invalid file:{0}".format(item))continuefname = ftype[0] # a.png -> aftype = ftype[1] # a.png -> pngsupport_ftype_list = ['png', 'PNG', 'jpeg', 'JPEG', 'gif', 'GIF', 'bmp']if ftype not in support_ftype_list:print("error: file type {0} not support, only support {1}".format(ftype, json.dumps(support_ftype_list)))continueabs_file = abs_itemif item.find('_small') != -1: # 这是缩略图continuesmall_file = '{0}_small.{1}'.format(fname, ftype)abs_small_file = os.path.join(img_path, small_file) # 缩略图绝对路径if os.path.exists(abs_small_file):# 对应的 _small 缩略图已经存在continuecompress_status = compress_img(abs_file, 0.9, True)if not compress_status:print("compress_img fail:{0}", abs_file)continueim = Image.open(abs_file)original_size = im.sizelength = original_size[0]height = original_size[1]m = int(float(length) / 200.0) # 计算缩小比例 (缩略图限制 200 长度)new_length = int(float(length) / m)new_height = int(float(height) / m)im.thumbnail((new_length, new_height)) # 生成缩略图im.save(abs_small_file, ftype) # 保存缩略图print("save thumbnail img {0}".format(abs_small_file))relative_file = abs_file[len(github_img_host_base) + 1:] # 计算相对路径,用来拼接 cdnrelative_small_file = abs_small_file[len(github_img_host_base) + 1:]cdn_url_file = '{0}/{1}'.format(cdn_url_prefix, relative_file)cdn_url_small_file = '{0}/{1}'.format(cdn_url_prefix, relative_small_file)# 格式: 690.690;8.png;http://cdn_file_url;http://cdn_small_file_url;line = '{0}.{1};{2};{3};{4}'.format(length, height, item, cdn_url_file, cdn_url_small_file)photo_info_list.append(line)# end for loopprint('dir:{0} Done!'.format(img_path))return photo_info_listif __name__=='__main__':github_img_host_base = config.get('github_img_host_base')img_path = config.get('img_path')cdn_url_prefix = config.get('cdn_url_prefix')photo_info_json = config.get('photo_info_json')photo_info_list = []photo_info_list_has = []photo_info_list = thumbnail_pic(github_img_host_base, img_path, cdn_url_prefix)if os.path.exists(photo_info_json):with open(photo_info_json, 'r') as fin:photo_info_list_has = json.loads(fin.read())fin.close()photo_info_list_has.extend(photo_info_list) # 追加此次新增的 photo infowith open(photo_info_json, 'w') as fout:fout.write(json.dumps(photo_info_list_has, indent = 2))print("save photo_info_list to {0}".format(photo_info_json))fout.close()print("\nAll Done")
这里重点需要关注的是:
config = {# github 存储图片的仓库(本地仓库基准目录)'github_img_host_base': '/Users/smaug/blogimg_2',# 会对这个目录下的所有文件夹进行遍历,相同目录生成_samll 的 缩略图'img_path': '/Users/smaug/blogimg_2/rebootcat/photowall',# cdn 前缀'cdn_url_prefix': 'https://cdn.jsdelivr.net/gh/smaugx/MyblogImgHosting_2',# hexo 博客存放 photos 信息的 json 文件'photo_info_json': '/Users/smaug/blog_rebootcat/source/photos/photoslist.json',}
简单解释一下这个脚本:
- github_img_host_base: 这个目录也就是本地的仓库目录,绝对路径(上面克隆的仓库对应的本地文件夹路径)
- img_path: 我单独新建了 rebootcat/photowall 目录存放瀑布流图片,对应本地的路径
- cdn_url_prefix:jsdelivr cdn url 前缀,只需要更改成你自己的github 用户名以及仓库名
- photo_info_json: photoslist.json 路径
上面几个参数一定要配置对了。
那么简单解释一下脚本的功能:
脚本会递归的查找 img_path 目录下的图片,然后进行一定的压缩(99%),这里的压缩目的并非真的是压缩,而是为了去除一些敏感信息,比如 GPS 信息。注意这里会覆盖掉原始图片。然后会生成图片的缩略图,同时根据上面的几个配置参数,生成两个 cdn url,一个对应的是原始图片的 cdn url,一个是缩略图的 cdn url.
然后执行:
python phototool.py
脚本执行完,就会增量生成 photoslist.json,可以先打开检查下对不对,或者把里面的 cdn url 复制出来从浏览器看能不能访问。
注意需要把本地图片仓库推送到远程。
这个 phototool.py 脚本你可以随便放在哪里,当你更新图片之后重新执行一遍就可以了。当然你也可以像我一样,跟网站源码直接放一起,所以你可以看到,我直接放到了 js 目录。
更新图片
把新图片放到本地仓库,然后执行:
python phototool.py
检查一下 photoslist.json 文件对不对,然后发布博客:
hexo d -g
发布之后,记得把本地图片仓库推送到远端,不然 jsdelivr 无法访问到。
至此,一个相册瀑布流就制作完成了!
The End
由于我是采用回忆的方式来写的博文,所以文中可能会有一些小的修改或者配置我忽略了,不过问题不大,大家如果碰到问题了可以自行研究一下,能解决的。
采用 github 作为图床来存放大量的瀑布流图片墙,方案是没问题的,只不过可能由于仓库容量的限制,需要在 github 上构建多个图片仓库。
对于我来说,github 图片仓库主要用来存放博文中涉及到的图片。至于图片墙,我再另想办法吧。
Blog:
rebootcat.com
email: linuxcode2niki@gmail.com
2020-09-19 于杭州
By 史矛革
相关文章:

【分享几个日常巡检 监控数据库的语句】
查看数据库表空间语句 select df.tablespace_name "表空间名",totalspace "总空间M",freespace "剩余空间M",round((1-freespace/totalspace)*100,2) "使用率%" from (select tablespace_name,round(sum(bytes)/1024/1024) totalspa…
AI换脸、声音篡改等,明确写入新版《民法典》
来源 | HyperAI超神经5 月 28 日,十三届全国人大三次会议表决通过了《中华人民共和国民法典》(以下简称《民法典》)第四编人格权中的第四章肖像权,明确提出了以信息技术手段,对于他人肖像、声音等权益的侵害认定。《民…

awk: (FILENAME=- FNR=1) 致命错误: 试图访问字段 -2
执行:awk {print $(NF-2)} aa.log出现错误:awk: (FILENAMEaa.log FNR1) 致命错误: 试图访问字段 -2可能和aa.log中数据有关系:改为:awk NF>1{print $(NF-2)} aa.log转载于:https://blog.51cto.com/henly/1786692

迁移博客到香港虚拟空间
原文: https://rebootcat.com/2020/09/20/virtual_space_blog/ 缘起 我的博客一直采用的是 github pages 来托管,中间断断续续的也没怎么管理过,偶尔写几篇博客,所以也就没怎么关心过访问速度,搜索引擎收录等问题。 …
自动化神经网络理论进展缓慢,AutoML算法的边界到底在哪?
作者 | 夕颜出品 | CSDN(ID:CSDNnews)「AI 技术生态论」 人物访谈栏目是 CSDN 发起的百万人学 AI 倡议下的重要组成部分。通过对 AI 生态顶级大咖、创业者、行业 KOL 的访谈,反映其对于行业的思考、未来趋势判断、技术实践,以及成…

让电脑通过gns3里的路由器上网
题目我感觉写的不好,反正就是这个意思,看下文 头几天有网友问cisco2811路由器怎么用ACL封掉QQ,当时就想帮他,但是手里又没有cisco路由器,只有GNS3 cisco模拟器。 现在的问题就是要用gns3模拟器的路由器充当真实工作中的…

文件上传的渐进式增强
文件上传是最古老的互联网操作之一。 20多年了,它几乎没变,还是原来的样子:操作麻烦、缺乏交互、用户体验不佳。在这个新技术日新月异的时代,显得非常落伍。 网页开发者们想了很多办法,试图提升文件上传的功能和操作体…

使用 mkdocs 搭建个人 wiki 站点
原文: https://rebootcat.com/2020/09/20/wiki/ why wiki 博客通常是用来记录一些完整的文章,每篇文章有一个主题。但是我想把平日里的一些笔记也记录到我的博客里,但笔记是零散的,随时的,不是完整的一个主题。所以打…
追忆童年,教你用Python画出儿时卡通人物
作者 | 张同学来源 | 凹凸数据大家好,我是张同学。又到一年一度的国际儿童节,作为逢节必过的程序猿,怎么可以放过这个学习技能的机会呢?于是,今天我们来学习 Python 的 Turtle 库绘制童年的卡通人物,一起做…

xx学OD -- 消息断点 RUN跟踪(上)
这一篇讲的是 消息断点和RUN跟踪的简单知识这一篇没怎么看明白 大概使用知道了 怎么用不太清楚。介绍本次软件特点输入后木有反应(纱布垃圾的。。哈哈)启动OllyDBG载入这个程序,F9让它运行。这个程序按我们前面讲的采用字串参考或函数参考的方法都很容易断下来。…

iOS-UIWebView添加头部和尾部
2019独角兽企业重金招聘Python工程师标准>>> 前言 项目中使用UIWebView显示本地或者是服务器上的页面很容易,但是仅限于显示页面,可控性并不高,如果有需要在头部和尾部加上原生的view,显示部分信息相对于全部使用UIWeb…

epoll 入门例子 tcp server/client
原文: https://rebootcat.com/2020/09/26/epoll_examples/ 复习一下 上一篇博文 epoll原理深入分析 详细分析了 epoll 底层的实现原理,如果对 epoll 原理有模糊的建议先看一下这篇文章。那么本文就开始用 epoll 实现一个简单的 tcp server/client。 本…
张红忠:智慧化时代,如何通吃5G模组、AIoT?
受访者 | 张红忠,日海智能副总裁、云AIoT创新中心总经理记者 | Aholiab,编辑 | 邓晓娟出品 | AI科技大本营(ID:rgznai100)日海智能是目前国内AIoT领域的头部企业,以AIoT为核心,形成了5G&AI物联网终端、…

JQUERY打造隐藏在左侧的弹性弹出菜单
代码简介: 隐藏在左侧的弹性弹出菜单,从淘宝扣下来的,也可作为JAvaScript缓冲动画的典型教程。本弹性菜单可扩展性强,实际上不光可以做成菜单,也可布局一些图文混排的内容或一段视频,总之被弹出的内容是在一…

Num55 boss09(activiti安装以及API)
2019独角兽企业重金招聘Python工程师标准>>> 安装流程设计器插件: 使用框架提供的方式创建23张表: 流程部署,定义,启动&查询,办理任务: 流程的部署,查询,删除 & …

模仿nginx修改进程名
个人博客原文: https://rebootcat.com/2020/10/25/setproctitle/ nginx 进程名 使用 nginx 的过程中,我们经常看到 nginx 的进程名是不同的,如下: $ ps -ef |grep nginx smaug 1183 1115 0 05:46 pts/2 00:00:00 grep …
机器学习模型的超参数优化 | 原力计划
作者 | deephub责编 | 王晓曼出品 | CSDN博客头图 | CSDN付费下载自东方IC引言模型优化是机器学习算法实现中最困难的挑战之一。机器学习和深度学习理论的所有分支都致力于模型的优化。机器学习中的超参数优化旨在寻找使得机器学习算法在验证数据集上表现性能最佳的超参数。超参…

准备IE--复习NP,NP从头开始,每天学一点,就多一点收获
2011-07-07 今天开始重新开始NP!每天一实验,加油!写下心路历程,为自己加油!转载于:https://blog.51cto.com/sunchangsheng/605482

[20160608]自治事务引起死锁.txt
[20160608]自治事务引起死锁.txt --链接http://www.itpub.net/thread-2060966-2-1.html上的讨论,很久以前也遇到过 --(http://blog.itpub.net/267265/viewspace-721262/),时间有点久远,自己重复测试看看: 1.环境: SCOTTtest> &r/ver1 PORT_STRING V…

动感效果的TAB选项卡 jquery 插件
动感效果的TAB选项卡 jquery 插件 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns"http://www.w3.org/1999/xhtml"><head><me…

Linux上隐藏进程名(初级版)
缘起 上一篇博文 模仿nginx修改进程名 中提到了一种修改进程名的方法,就像 nginx 一样,给不同进程命名为 master 以及 worker 等。那么能不能把新进程名设置为空字符串呢?如果能,又会有哪些应用场景呢? 答案可能是能…
神操作!一行Python代码搞定一款游戏?给力!
来源:pypl编程榜一直以来Python长期霸占编程语言排行榜前三位,其简洁,功能强大的特性使越来越多的小伙伴开始学习Python 。甚至K12的同学都开始学习Python 编程。新手入门的时候趣味性其实最重要的。那么一行Python 代码到底能玩出什么花样&a…

jquery对所有input type=text的控件赋值
function resetData() { $("input[typetext]").each( function() { $(this).attr("value",""); } ); }

free not return memory
个人博客:https://rebootcat.com/2020/11/05/free_mem/ 内存泄露? 观察到一台机器上的内存使用量在程序启动之后,持续增长,中间没有出现内存恢复。怀疑是不是出现了内存泄露的问题? 然后使用相关的内存分析工具进行了…

成大事必备9种能力
挑战生存的能力:善于在现实中寻找答案 1、摆正心态,敢于面对现实 对于那些不停地抱怨现实恶劣的人来说,不能称心如意的现实,就如同生活的牢笼&a…
懂语言者得天下:NLP凭什么被称为人工智能的掌上明珠?
受访者 | 简仁贤,竹间智能创始人&CEO记者 | 邓晓娟出品 | AI科技大本营(ID:rgznai100)随着技术的发展,大数据、云计算、人工智能、区块链都慢慢地为人熟知。2016 年 Google 推出 AlphaGo,让人工智能走进了大众的视…

[转]SIFT特征提取分析
SIFT(Scale-invariant feature transform)是一种检测局部特征的算法,该算法通过求一幅图中的特征点(interest points,or corner points)及其有关scale 和 orientation 的描述子得到特征并进行图像特征点匹配࿰…

博客大事记之迁移博客到香港主机
个人博客:https://rebootcat.com/2020/11/10/move_blog_hk/ 前言 之前其实已经写过一篇博文: 迁移博客到香港虚拟空间,那为什么又要写这篇博客呢? 上次其实是把我的博客迁移到一个香港的虚拟空间里,但是不到半年的时…
限时福利:腾讯高级专家手把手教你打造 OCR 神器!
OCR,英文全称即 optical characters recognition(光学字符识别),通过服务器把图片上的文字识别出来,以供大家编辑使用,比如进出火车站的时候,已经可以自动识别的身份证;在道路行驶中…

C++与.net的编译方式
C和.Net程序采用了两种不同的编译方式。 通常一个C编写的程序,都是一次编译成二进制的代码,在相应的操作系统平台上直接执行即可。 而.Net程序采用两次编译的方式,用C#,VB.Net等语言写成的程序被编译成IL代码,通过CLR在…