Gin + GoCv + Element 简单搭建图片风格迁移网站

news/2024/5/20 21:51:46/文章来源:https://blog.csdn.net/weixin_47560078/article/details/120356824

成品效果

输入:jpg/png 格式图片

输出:风格迁移后的图片

目录结构

# tree├─controller // 控制器
├─models // 风格迁移模型
│  ├─eccv16
│  └─instance_norm
├─router // 路由转发
├─static // 静态资源
├─sys // 系统配置
├─templates // html 模板
├─upload // 上传或者生成的图片
│  └─images
│      ├─input
│      └─output
└─utils // 封装的工具

简单构建 Web 网页

使用 Element 的上传组件和图片组件:

 index.tmpl

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><!-- import CSS --><link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"><!-- import axios --><!-- <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> --><!-- import Vue before Element --><script src="https://unpkg.com/vue/dist/vue.js"></script><!-- import JavaScript --><script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head><body><div id="app"><el-upload class="upload-demo" ref="upload" action="http://127.0.0.1:8080/upload" :on-success="handleSuccess" :on-preview="handlePreview" :on-remove="handleRemove" :limit="1" :file-list="fileList" list-type="picture" :auto-upload="false"><el-button slot="trigger" size="small" type="primary">选取文件</el-button><el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload" v-loading.fullscreen.lock="fullscreenLoading" element-loading-text="拼命加载中">转换图片</el-button><div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过8Mbit</div></el-upload><div class="demo-image__lazy" style="margin-top:30px;"><el-image v-for="url in urls" :key="url" :src="url" lazy></el-image></div></div>
</body>
<script>new Vue({el: '#app',data() {return {fileList: [],urls: [],fullscreenLoading: false};},methods: {// 提交表单submitUpload() {this.$refs.upload.submit();this.fullscreenLoading = true;},// 移除图片handleRemove(file, fileList) {console.log(file, fileList);},// 预览略缩图handlePreview(file) {console.log(file);},// 超出限制handleExceed(files, fileList) {this.$message.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);},// 加载成功handleSuccess(response, file, fileList){// console.log(response.data);this.urls = response.urls;this.fullscreenLoading = false;}}})
</script></html>

封装系统变量

package sysconst OUT_PATH string = "D:\\GoFiles\\simple-gocv-web\\upload\\images\\output\\"const IN_PATH string = "D:\\GoFiles\\simple-gocv-web\\upload\\images\\input\\"const IMG_URL string = "http://127.0.0.1:8080/upload/images/output/"var MODELS_NAME = []string{"D:\\GoFiles\\simple-gocv-web\\models\\eccv16\\composition_vii.t7","D:\\GoFiles\\simple-gocv-web\\models\\eccv16\\la_muse.t7","D:\\GoFiles\\simple-gocv-web\\models\\eccv16\\starry_night.t7","D:\\GoFiles\\simple-gocv-web\\models\\eccv16\\the_wave.t7","D:\\GoFiles\\simple-gocv-web\\models\\instance_norm\\candy.t7","D:\\GoFiles\\simple-gocv-web\\models\\instance_norm\\feathers.t7","D:\\GoFiles\\simple-gocv-web\\models\\instance_norm\\la_muse.t7","D:\\GoFiles\\simple-gocv-web\\models\\instance_norm\\mosaic.t7","D:\\GoFiles\\simple-gocv-web\\models\\instance_norm\\the_scream.t7","D:\\GoFiles\\simple-gocv-web\\models\\instance_norm\\udnie.t7",
}

工具类

uuidUtil :保证图片文件名不重复。

package utilsimport uuid "github.com/satori/go.uuid"/*
生成全局唯一 uuid
*/
func GetUUID() string {return uuid.NewV4().String()
}

saveImgUtil :保存图片返回访问路径

package utilsimport ("image""image/jpeg""os". "simple-web/sys"
)func SaveImg(src image.Image) string {// 写入新文件imgId := GetUUID() + ".jpg"path := OUT_PATH + imgIdf, _ := os.OpenFile(path, os.O_RDWR|os.O_CREATE, os.ModePerm)defer f.Close()jpeg.Encode(f, src, nil)// 返回图片路径return IMG_URL + imgId
}

dnnUtil :进行图片风格迁移

package utilsimport ("fmt""image""log". "simple-web/sys""gocv.io/x/gocv"
)func GetTransferResult(deviceID string) []string {var res []stringfor i := 0; i < len(MODELS_NAME); i++ {res = append(res, DNNStyleTransfer(deviceID, MODELS_NAME[i]))}return res
}func DNNStyleTransfer(deviceID string, model string) string {if len(deviceID) == 0 || len(model) == 0 {log.Fatal("How to run:\ndnn-style-transfer [videosource] [modelfile] ([backend] [device])")}// 使用默认参数backend := gocv.NetBackendDefaulttarget := gocv.NetTargetCPU// 读取的图片位置img := gocv.IMRead(deviceID, gocv.IMReadColor)defer img.Close()// 打开下载好的 DNN 风格迁移模型net := gocv.ReadNet(model, "")if net.Empty() {log.Fatalf("Error reading network model from : %v\n", model)}defer net.Close()net.SetPreferableBackend(gocv.NetBackendType(backend))net.SetPreferableTarget(gocv.NetTargetType(target))fmt.Printf("Start reading device: %v\n", deviceID)// 将 image Mat 转换为 DNN 风格迁移模型可以分析的 640x480 Blobblob := gocv.BlobFromImage(img, 1.0, image.Pt(640, 480), gocv.NewScalar(103.939, 116.779, 123.68, 0), false, false)// 把转换成的 Blob 放进转换器net.SetInput(blob, "")// 通过网络运行一个向前传递probMat := net.Forward("")sz := probMat.Size()dims := sz[2] * sz[3]out := gocv.NewMatWithSize(480, 640, gocv.MatTypeCV8UC3)// 取 blob 并从中获取可显示的 image Mat 图像for i := 0; i < dims; i++ {r := probMat.GetFloatAt(0, i)r += 103.939g := probMat.GetFloatAt(0, i+dims)g += 116.779b := probMat.GetFloatAt(0, i+dims*2)b += 123.68out.SetUCharAt(0, i*3, uint8(r))out.SetUCharAt(0, i*3+1, uint8(g))out.SetUCharAt(0, i*3+2, uint8(b))}// 保存图片,得到返回路径i, err := out.ToImage()if err != nil {log.Fatal(err)}path := SaveImg(i)probMat.Close()blob.Close()out.Close()return path
}

控制器

控制文件上传和返回结果。

package controllerimport ("log""net/http". "simple-web/sys". "simple-web/utils""github.com/gin-gonic/gin"
)// 首页
func Index(c *gin.Context) {c.HTML(http.StatusOK, "index.tmpl", nil)
}/*
上传图片并实现风迁移,渲染到页面
*/
func Upload(c *gin.Context) {// 单文件file, _ := c.FormFile("file")log.Println(file.Filename)// 上传文件至指定目录dst := IN_PATH + GetUUID()err := c.SaveUploadedFile(file, dst)if err != nil {log.Println(err)}outDst := GetTransferResult(dst)log.Println(outDst)// 渲染/*c.HTML(http.StatusOK, "index.tmpl", gin.H{".bodyText": outDst,})*/// 返回结果c.JSON(http.StatusOK, gin.H{"status": "success","urls":   outDst,})
}

定义路由

package routerimport ("net/http". "simple-web/controller""github.com/gin-gonic/gin"
)/*
InitRouter 路由初始化
*/
func InitRouter() *gin.Engine {router := gin.Default()// 加载 templates 文件夹下所有的 tmplrouter.LoadHTMLGlob("templates/*")router.GET("/index", Index)// 文件上传router.POST("/upload", Upload)// ============== 静态资源/文件 ==============// 加载静态资源,例如网页的css、jsrouter.Static("/static", "./static")// 加载静态资源,一般是上传的资源,例如用户上传的图片router.StaticFS("/upload", http.Dir("upload"))// 加载单个静态文件// r.StaticFile("/favicon.ico", "./static/favicon.ico")return router
}

main 入口

package mainimport (. "simple-web/router"
)func main() {r := InitRouter()// Listen and Server in 0.0.0.0:8080r.Run(":8080")
}

完整项目

效果测试

 

Docker 部署项目

其实该镜像有问题,golang 版本低,dnn 函数出错。

自制 gocv 环境镜像

# 拉取 centos7 镜像
docker pull centos:7# 启动镜像
docker run --name="centos7" -it -d --rm -p 8082:8082 centos:7# 进入容器
docker exec -it centos7 bash# 安装基础命令
yum install -y wget gcc make# 安装 go 和 安装 cmake 在网上有很多教程# 安装 gocv
go get -u -d gocv.io/x/gocv && cd $GOPATH/pkg/mod/gocv.io/x/gocv@v0.28.0 && make install// 如果报错找不到 opencv4.pc ,不要紧,设置变量
echo 'export PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig' >>/etc/profile
source /etc/profile// 如果报错找不到 XXX.so 文件,不要紧,就在 /usr/local/lib64 目录下
vim /etc/ld.so.conf.d/opencv.conf
添加一行 /usr/local/lib
:wq保存退出后执行 ldconfig 重载配置

完成环境安装之后验证环境:

[root@494d90036f52 ~]# source /etc/profile
[root@494d90036f52 ~]# go version
go version go1.16 linux/amd64
[root@494d90036f52 ~]# cd $GOPATH
[root@494d90036f52 gowork]# cd pkg/mod/gocv.io/x/gocv\@v0.28.0/
[root@494d90036f52 gocv@v0.28.0]# go run ./cmd/version/main.go 
gocv version: 0.28.0
opencv lib version: 4.5.3
[root@494d90036f52 gocv@v0.28.0]# 

ok,exit 退出准备 docker commit 打包镜像,其实应该用 Dockerfile 文件构建镜像的,但是有很多不可控的因素和一些奇奇怪怪的报错,因此我为简便起见使用 docker commit 指令。

# 查看当前运行的容器
docker ps# 打包镜像
docker commit centos7 gocv:latest# 查看打包后的镜像
docker images

现在已经有 go 和 gocv 环境的镜像了,现在构建项目的 Dockerfile :

FROM gocv:latest
WORKDIR $GOPATH/src/simple-gocv-web
ADD . ./
ENV TZ=Asia/Shanghai
ENV GO111MODULE=on
ENV GOPROXY="https://goproxy.io"
RUN source /etc/profile && \
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone && \
go build -o simple-gocv-web .
EXPOSE 8083
ENTRYPOINT  ["./simple-gocv-web"]

打包项目镜像

docker build -t demo .

 运行项目

docker run -d -it --rm -p 8083:8083 demo

运行报错:

terminate called after throwing an instance of 'cv::Exception'what():  OpenCV(4.5.3) /tmp/opencv/opencv-4.5.3/modules/dnn/src/torch/THDiskFile.cpp:496: error: (-2:Unspecified error) cannot open <models\eccv16\composition_vii.t7> in mode r  in function 'THDiskFile_new'

 无法加载模型,可能是没有识别到相对路径,尝试修改为绝对路径:

重新打包运行:

postman 测试:成功! 

可能是反斜杠 “/” 与双斜杠 ”\\“ 不兼容的问题,upload 文件夹采用相对路径时却能正常识别,而 models 文件夹无法识别。

网页测试:成功!

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

手机访问网站 点击手机号码直接拨打电话

分享一下我老师大神的人工智能教程&#xff01;零基础&#xff0c;通俗易懂&#xff01;http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章。分享知识&#xff0c;造福人民&#xff0c;实现我们中华民族伟大复兴&#xff01; 手机访问网站,点击手机号码直接拨打电话: …

使用IntelliJ IDEA开发SpringMVC网站

转自https://my.oschina.net/gaussik/blog/385697 1.安装jdk&#xff0c;maven和tomcat 2.创建maven web项目 Create New Project 最后生成结果如下图&#xff0c;注意左侧部分 上侧部分选择Auto-Import就好 如果生成过慢&#xff0c;可以参看下面两篇文章&#xff1a; 文章1&a…

回首10年前的30个最受欢迎的网站

10年前的Web技术还比较落后&#xff0c;浏览器功能也非常有限&#xff0c;你知道现在最受欢迎的这些网站&#xff0c;在10年前甚至更早的时候是什么样子吗&#xff1f;文中为你揭示包括Google、雅虎、eBay、维基百科等网站的老面孔&#xff1a; 1. Google (1998) Google (1998…

让你的Onedrive网盘秒变网站,文件展示,直连下载,视频在线播放

之前我们介绍了免费的5TB的Onedrive网盘&#xff0c;不但能做本地硬盘使用&#xff0c;还能扩展你的硬盘&#xff0c;今天我们就来介绍一下另一款Onedrive网盘的神器OneIndex,这是针对Onedrive网盘的一个开源程序。可以将Onedrive存储的文件展示&#xff0c;直连下载。视频还能…

LAMP网站架构方案分析

LAMP&#xff08;Linux-Apache-MySQL-PHP&#xff09;网站架构是目前国际流行的Web框架&#xff0c;该框架包括&#xff1a;Linux操作系统&#xff0c;Apache网络服务器&#xff0c;MySQL数据库&#xff0c;Perl、PHP或者Python编程语言&#xff0c;所有组成产品均是开源软件&a…

如何更改VS2005调试网站的浏览器类型

选择网站根目录&#xff0c;右键单击 选择“浏览方式” 在这里就可以设置浏览器的类型了 转载于:https://www.cnblogs.com/qishichang/archive/2007/11/25/971588.html

微软官宣IE将“退役”,老网站如何 实现在Chrome、Firefox中兼容运行?

问题 美国微软公司为了推广其Chromium内核的Edge浏览器&#xff0c;在2021年5月19日突然宣布&#xff0c;自2022年6月15日起&#xff0c;绝大多数版本的Windows 10系统将不再支持IE浏览器&#xff0c;因此IE即将彻底退出互联网的舞台。具体来说微软决定将不再支持Windows 10所…

Python必去的6个网站

1.The Hitchhiker’s Guide to Python。 equests作者创建的网站&#xff0c;对于Python的方方面面都有指导作用 2. Python 3 Module of the Week 和 Python Module of the Week。 Python 3 Module of the Week系列文章&#xff0c;每篇介绍一个 Python 标准库的使用 3. …

你的网站被流量冲崩了吗?稳住!ab来帮你了

【来源】 ab 全称 Apache Benchmar , 顾名思义是Apache提供的一种性能测试工具。主要作用是检测web服务每秒可以处理多少个请求。它可以用于apache、IIs、tomcat、nginx等服务器的简单压力测试 【语法】 格式&#xff1a;ab [options] path 其中options参数常用有以下&#xf…

推荐大家研究一个网站tineye.com

http://www.tineye.com/&#xff0c;这个站点做得很有想法&#xff0c;详细体验我过几天发出&#xff0c;有兴趣的朋友可以先看看。 刚刚用这个站点上传了我硕士毕业的标准照&#xff0c;回顾了那段意气奋发的年代。

如何应对高并发 —— 动态网站静态化

零. 前言 为了应对高并发&#xff0c; 大多数网站在更新不频繁的页面都做了动态网页静态化处理。 典型的如&#xff1a; 淘宝的首页、 网易新闻的首页等。 当然这些网站加载速度这么快&#xff0c; 不仅仅是静态化&#xff0c; 还有 CDN、 缓存等各个方面的优化。 从阿里在 Inf…

HTML5移动端手机网站开发流程

最近一直在研究移动手机网站的开发&#xff0c;发现做手机网站没有想象中的那么难。为什么会这么说呢&#xff1f;我们试想下:我们连传统的PC网站都会做&#xff0c;难道连一个小小的手机网站难道都搞不定吗&#xff1f;其实手机网站就是一个微缩版的PC网站罢了&#xff01;至于…

网站pc版转成手机版的三种方法

现在做自媒体博客的朋友有很多&#xff0c;可是&#xff0c;大家的自媒体博客都是PC版&#xff0c;只适用于电脑&#xff0c;平板上面&#xff0c;对于手机来说的话就不适合了&#xff0c;影响用户体验。下面&#xff0c;邵连虎博客就教大家三种方法把自媒体博客PC版转换成手机…

一些GIS数据网站分享

在平时的工作和学习中收集了不少的GIS数据的网站&#xff0c;给大家分享一下&#xff0c;整理不易&#xff0c;还请大家多多支持&#xff0c;后续会根据收集的数据网站继续更新&#xff0c;我都是根据我自己收集的情况推荐&#xff0c;涵盖可能不是很全&#xff0c;也欢迎大家补…

分享12个非常好的免费矢量资源网站

原文作者&#xff1a;梦想 原文出处&#xff1a;http://www.cnblogs.com/lhb25/archive/2011/04/08/2003802.html 在工作中&#xff0c;Web设计师经常需要到网上查找一些免费资源以更快更好的完成设计任务。这些资源都是到用时方恨少啊&#xff0c;所以今天本文与大家分享12个…

从0到1搭建一个网站

引言&#xff1a;如何从0倒1搭建一个网站。(记录我自己搭建过程&#xff0c;不涉及企业推荐) 目录 引言&#xff1a;如何从0倒1搭建一个网站。(记录我自己搭建过程&#xff0c;不涉及企业推荐) 所需要准备的东西 开始搭建(以阿里服务器为例) 搭建服务器环境 部署项目到网…

大型互联网站解决高并发的常见策略

出处&#xff1a;http://www.javabloger.com/article/high-concurrent-common-coping-strategies.html 一个运营的系统在正式上线后将会遇到各种层级的高并发请求&#xff0c;因此我们必须对此做出相应的策略和技术解决方案&#xff0c;首先我们需要认清系统的高并发由3个层面导…

Flask全栈开发案例(二)——Flask+Angular+Mongodb管理系统,创建一个热门游戏参数网站

文章目录 项目背景数据初始化主页展示游戏收藏详情展示新增与编辑源码获取 项目背景 该项目爬取PS4游戏论坛中对于的各个游戏参数的数据&#xff0c;进行web门户展示&#xff0c;设置用户登陆&#xff0c;可针对感兴趣的游戏内容进行增删改查操作。支持登陆用户进行评论互动。…

域名,网站名,URL解析

转载至&#xff1a;https://jingyan.baidu.com/article/2c8c281df0afd00008252aa7.html 什么是域名&#xff1f;现实中&#xff0c;域名使用的实在太多了&#xff0c;但域名的详细含义你理解么&#xff1f;你知道域名是什么吗&#xff1f;下面&#xff0c;小编将带你详解域名的…

用好这5个网站,月薪从4000变一万

Udacity https://cn.udacity.com/ Udacity 是一个自学编程网站&#xff0c;它的中文名字叫优达学城&#xff0c;你可以在上面学习所有的编程语言&#xff0c;课程大都是国外著名公司技术专家来教学的&#xff0c;而且很多课程都有翻译字幕。 edX https://www.edx.org/ 由麻…