之前寫了篇文章《超越前作,實作動漫風格遷移——AnimeGANv2》,里面提到使用AnimeGANv2實作人物動漫化,生成一個獨一無二對自己價值珍貴的頭像,不過操作起來有億點點麻煩,所以希望做一個小程式,直接在手機端就能一鍵生成專屬于自己的動漫頭像,下面是展示效果!!!

一、核心功能設計
該小程式想要實作的是將微信頭像或者選擇相冊中的照片動漫化,所以拆解需求后,整理的核心功能如下:
- 授權登錄獲取頭像及昵稱
- 選擇相冊中的圖片
- 點擊動漫化按鈕,呼叫Flask后端生成影像
- 保存影像
二、微信小程式前端實作步驟
首先新建一個空白的微信小程式專案,詳細步驟可以參考之前《Python+微信小程式開發(一)了解和環境搭建》的文章,
1.登錄界面
在pages/index/index.wxml設計頁面:
<view wx:if="{{canIUse}}">
<view class='header'>
<view class="userinfo-avatar">
<open-data type="userAvatarUrl"></open-data>
</view>
</view>
<view class="content">
<view>申請獲取以下權限</view>
<text>獲得您的公開資訊(昵稱,頭像等)</text>
</view>
<button wx:if="{{canIUse}}" class="loginBtn" type="primary" lang="zh_CN" bindtap="bindGetUserProfile" >
授權登錄
</button>
</view>
在pages/index/index.js添加用戶資訊驗證:
bindGetUserProfile(e) //當用戶點擊授權登錄按鈕觸發 bindGetUserInfo函式
{
var that=this
wx.getUserProfile({
desc: '用于完善會員資料', // 宣告獲取用戶個人資訊后的用途,后續會展示在彈窗中,請謹慎填寫
success: (res) => {
// console.log(res.userInfo)
var avantarurl=res.userInfo.avatarUrl;
wx.navigateTo({
url: '../../pages/change/change?url='+ avantarurl ,
})
},
fail:(res)=>{
console.log(1)
}
})
},
其中將頭像的url傳遞給avanta界面,
效果如下:
2.avantar頁面
在該頁面進行選取照片以及頭像動漫化,
在pages/avantar/avantar.wxml設計頁面:
<!--pages/avantar/avantar.wxml-->
<view class='preview'>
<view class="Imgtag">
<image class="tag" src='{{prurl}}' mode='aspectFit'></image>
</view>
<view class="bottomAll">
<button bindtap='selectImg' class="saveBtn">選擇圖片</button>
<button bindtap='generateAvantar' class="saveBtn">動漫化</button>
<button bindtap='save' class="saveBtn">保存頭像</button>
</view>
</view>
在pages/avantar/avantar.js定義函式:
其中onload函式接收index傳遞的url,
onl oad: function (options) {
if(options.url){
// console.log(options.url)
var path = this.headimgHD(options.url)
console.log(path)
this.setData({
image:path,
// image1:path,
// baseURL:path
})
}
其中chooseImage函式實作選擇圖片,
chooseImage() {
var that = this;
wx.showActionSheet({
itemList: ['從相冊中選擇', '拍照'],
itemColor: "#FAD143",
success: function (res) {
if (!res.cancel) {
wx.showLoading({
title: '正在讀取...',
})
if (res.tapIndex == 0) {
that.chooseWxImage1('album', 1)
} else if (res.tapIndex == 1) {
that.chooseWxImage1('camera', 1)
}
}
}
})
},
savePic函式保存照片,
savePic(e) {
let that = this
var baseImg = that.data.baseImg
//保存圖片
var save = wx.getFileSystemManager();
var number = Math.random();
save.writeFile({
filePath: wx.env.USER_DATA_PATH + '/pic' + number + '.png',
data: baseImg,
encoding: 'base64',
success: res => {
wx.saveImageToPhotosAlbum({
filePath: wx.env.USER_DATA_PATH + '/pic' + number + '.png',
success: function (res) {
wx.showToast({
title: '保存成功',
})
},
fail: function (err) {
console.log(err)
}
})
console.log(res)
},
fail: err => {
console.log(err)
}
})
},
generateAvantar函式呼叫postdata函式實作頭像動漫化,
generateAvantar:function(e){
var that = this
console.log(that.data.prurl)
wx.uploadFile({
url: 'http://127.0.0.1:8090/postdata',
filePath: that.data.prurl,
name: 'content',
success: function (res) {
console.log(res.data);
var resurl=JSON.parse(res.data)['resurl']
that.setData({
prurl: resurl
})
if (res) {
wx.showToast({
title: '轉換完成',
duration: 3000
});
}
},
fail: (res) =>{
console.log('fail===',res)
}
})
},
三、Flask后端實作步驟
1.配置RESTful路由方法
@app.route('/postdata', methods=['POST'])
def postdata():
f = request.files['content']
print(f)
user_input = request.form.get("name")
basepath = os.path.dirname(__file__) # 當前檔案所在路徑
src_imgname = str(uuid.uuid1()) + ".jpg"
upload_path = os.path.join(basepath, 'static/srcImg/')
if os.path.exists(upload_path)==False:
os.makedirs(upload_path)
f.save(upload_path + src_imgname)
# img = cv2.imread(upload_path + src_imgname, 1)
save_path = os.path.join(basepath, 'static/resImg/')
if os.path.exists(save_path) == False:
os.makedirs(save_path)
generateAvantar(src_imgname,upload_path,save_path)
resSets["value"] = 10
resSets["resurl"] = "http://127.0.0.1:8090" +'/static/resImg/' + src_imgname
return json.dumps(resSets, ensure_ascii=False)
該代碼主要接受前端傳來的圖片url,進行處理并且通過json傳回去,
2.呼叫AnimeGanv2實作動漫化
net = Generator()
net.load_state_dict(torch.load(args.checkpoint, map_location="cpu"))
net.to(args.device).eval()
# print(f"model loaded: {args.checkpoint}")
# os.makedirs(args.output_dir, exist_ok=True)
def load_image(image_path, x32=False):
img = cv2.imread(image_path).astype(np.float32)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
h, w = img.shape[:2]
if x32: # resize image to multiple of 32s
def to_32s(x):
return 256 if x < 256 else x - x%32
img = cv2.resize(img, (to_32s(w), to_32s(h)))
img = torch.from_numpy(img)
img = img/127.5 - 1.0
return img
def generateAvantar(src_imgname,upload_path,save_path):
image = load_image((upload_path+src_imgname), args.x32)
with torch.no_grad():
input = image.permute(2, 0, 1).unsqueeze(0).to(args.device)
out = net(input, args.upsample_align).squeeze(0).permute(1, 2, 0).cpu().numpy()
out = (out + 1)*127.5
out = np.clip(out, 0, 255).astype(np.uint8)
cv2.imwrite(os.path.join(save_path, src_imgname), cv2.cvtColor(out, cv2.COLOR_BGR2RGB))
該代碼主要是呼叫AnimeGanv2實作影像動漫化,
最后實作效果:

總結
其實這個小程式實作起來并不是很難,只需要配置基礎的深度學習環境和Flask編程就好了,再了解一些小程式基本的api,就能夠開發出來,大家有時間的可以去試試,后臺我已經搭好了,大家可以直接使用,可以看看效果,有什么問題可以在評論區留言,或者通過下方鏈接聯系我,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/377158.html
標籤:其他
上一篇:cgb2110-day11
