support some Edit Image

This commit is contained in:
Star 2024-11-03 11:36:02 +08:00
parent db308fe42b
commit 1c4932d005
6 changed files with 202 additions and 44 deletions

View File

@ -7,6 +7,8 @@ import (
_ "apigo.cc/ai/huoshan"
"apigo.cc/gojs"
_ "apigo.cc/gojs/console"
_ "apigo.cc/gojs/file"
_ "apigo.cc/gojs/util"
"github.com/ssgo/u"
)

View File

@ -1,8 +1,10 @@
import co from 'apigo.cc/gojs/console'
import file from 'apigo.cc/gojs/file'
import u from 'apigo.cc/gojs/util'
import ai from 'apigo.cc/ai'
let r = ai.huoshan.fastAsk('用一句话为你的主人写一段生成在山顶喝咖啡的图片的提示词', co.print, {
systemPrompt: '你的主人很美丽,喜欢戴帽子'
systemPrompt: '你的主人是个年轻姑娘,很美丽,喜欢戴帽子'
})
co.println()
co.info('生成的提示词:', r.result)
@ -16,9 +18,20 @@ let r2 = ai.huoshan.makeImage({
co.info('生成的图片:', r2.results[0])
let r3 = ai.huoshan.makeImageKeepIP({
prompt: '女孩,骑马在草原上狂奔,天上的云朵,有太阳,有小鸟',
prompt: '年轻姑娘,表情悲伤,骑马在草原上狂奔,天上的云朵,有太阳,有小鸟',
width: 1280,
height: 720,
ref: [r2.results[0]],
})
co.info('生成角色一致的图片:', r3.results[0])
let r3s = ai.huoshan.changeEmotion(r3.results[0], { target_emotion: 'liwo' })
co.info('梨涡笑:', r3s.result)
let r3p = ai.huoshan.makeFacePretty(r3s.result)
file.write('test.jpg', u.unBase64(r3p.result))
co.info('美颜后:', 'test.jpg')
let r4 = ai.huoshan.getHumanSegment(r3p.result)
file.write('test_mask.jpg', u.unBase64(r4.result))
co.info('角色主体:', 'test_mask.jpg')

View File

@ -18,10 +18,17 @@ func init() {
EmbeddingConfigs: defaultConf.Embedding,
ImageConfigs: defaultConf.Image,
VideoConfigs: defaultConf.Video,
EditConfigs: defaultConf.Edit,
AsrConfigs: defaultConf.Asr,
TtsConfigs: defaultConf.Tts,
Chat: Chat,
Embedding: Embedding,
MakeImage: MakeImage,
// MakeVideo: MakeVideo,
// GetVideoResult: GetVideoResult,
Edit: Edit,
// Scan: Scan,
// Asr: Asr,
// Tts: Tts,
})
}

View File

@ -6,58 +6,80 @@ image:
width: 1024
height: 1024
makeImageHD:
model: "high_aes_general_v20_L:general_v2.0_L"
model: high_aes_general_v20_L:general_v2.0_L
width: 512
height: 512
extra:
req_schedule_conf: general_v20_9B_rephraser
use_sr: true
use_pre_llm: true
makeCartoon:
model: high_aes:anime_v1.3.1
width: 1024
height: 1024
extra:
req_schedule_conf: general_v20_9B_rephraser
use_sr: true
use_pre_llm: true
makeImageKeepIP:
model: "high_aes_general_v14_ip_keep:general_v1.4_ip"
model: high_aes_general_v14_ip_keep:general_v1.4_ip
width: 1024
height: 1024
makeAmericanComics:
model: "img2img_photoverse_american_comics"
model: img2img_photoverse_american_comics
make3DWeird:
model: "img2img_photoverse_3d_weird"
model: img2img_photoverse_3d_weird
makeCyberpunk:
model: "img2img_photoverse_cyberpunk"
model: img2img_photoverse_cyberpunk
makeBabi:
model: "img2img_xiezhen_babi_niuzai"
model: img2img_xiezhen_babi_niuzai
extra:
beautify_info:
whitening: 2
dermabrasion: 2
makeIDPhoto:
model: "img2img_photoverse_executive_ID_photo"
# ModelDoubaoLite4k = "Doubao-lite-4k"
# ModelDoubaoLite32k = "Doubao-lite-32k"
# ModelDoubaoLite128k = "Doubao-lite-128k"
# ModelDoubaoPro4k = "Doubao-pro-4k"
# ModelDoubaoPro32k = "Doubao-pro-32k"
# ModelDoubaoPro128k = "Doubao-pro-128k"
# ModelDoubaoPro256k = "Doubao-pro-256k"
# ModelDoubaoEmbedding = "Doubao-embedding"
# ModelDoubaoEmbeddingLarge = "Doubao-embedding-large"
# ModelT2I2L = "high_aes_general_v20_L:general_v2.0_L"
# ModelT2I2S = "high_aes_general_v20:general_v2.0"
# ModelT2IXL = "t2i_xl_sft"
# ModelI2IXL = "i2i_xl_sft"
# ModelT2I14 = "high_aes_general_v14"
# ModelI2I14IP = "high_aes_general_v14_ip_keep"
# ModelAnime13 = "high_aes:anime_v1.3"
# ModelAnime131 = "high_aes:anime_v1.3.1"
# ModelPhotoverseAmericanComics = "img2img_photoverse_american_comics" // 美漫风格
# ModelPhotoverseExecutiveIDPhoto = "img2img_photoverse_executive_ID_photo" // 商务证件照
# ModelPhotoverse3dWeird = "img2img_photoverse_3d_weird" // 3d人偶
# ModelPhotoverseCyberpunk = "img2img_photoverse_cyberpunk" // 赛博朋克
# ModelXiezhenGubao = "img2img_xiezhen_gubao" // 古堡
# ModelXiezhenBabiNiuzai = "img2img_xiezhen_babi_niuzai" // 芭比牛仔
# ModelXiezhenBathrobe = "img2img_xiezhen_bathrobe" // 浴袍风格
# ModelXiezhenButterflyMachin = "img2img_xiezhen_butterfly_machin" // 蝴蝶机械
# ModelXiezhenZhichangzhengjianzhao = "img2img_xiezhen_zhichangzhengjianzhao" // 职场证件照
# ModelXiezhenChristmas = "img2img_xiezhen_christmas" // 圣诞
# ModelXiezhenDessert = "img2img_xiezhen_dessert" // 美式甜点师
# ModelXiezhenOldMoney = "img2img_xiezhen_old_money" // old money
# ModelXiezhenSchool = "img2img_xiezhen_school" // 最美校园
model: img2img_photoverse_executive_ID_photo
makeOutpainting:
model: i2i_outpainting
make3DStyle:
model: img2img_disney_3d_style
makeCartoonStyle:
model: img2img_cartoon_style
edit:
getHumanSegment:
action: HumanSegment
refine: 1
return_foreground_image: 1
changeEmotion:
action: EmotionPortrait
# jiuwo: 酒窝笑
# liwo: 梨窝笑
# big_smile_white_teeth: 露牙大笑
# classic_white_teeth: 露牙标准笑
# cool: 耍酷
# sad: 悲伤
# tight_smile: 勉强笑
target_emotion: big_smile_white_teeth
changeHair:
action: EmotionPortrait
# 101: 刘海(默认)
# 201: 长发
# 301: 刘海加长发
# 401: 中程度增发
# 402: 轻程度增发
# 403: 重程度增发
# 502: 轻程度卷发
# 503: 重程度卷发
# 603: 短发(要求输入尺寸<2048x2048若输入大于2048x2048的图片输出的图片会被resize成最长边2048)
# 801: 金发
# 901: 直发
# 1001: 头发去油(轻微效果,原图中此问题建议较为明显)
# 1101: 补发际线(调整过高的发际线,轻微效果,原图中此问题建议较为明显)
# 1201: 头发柔顺 (轻微效果,原图需有较大发型区域,原图中此问题建议较为明显)
# 1301: 补发缝(轻微效果,填补头发区域中的头皮部分,原图中此问题建议较为明显)
hair_type: 101
makeFacePretty:
action: FacePretty
do_risk: false
multi_face: 1
beauty_level: 1

114
gc.go
View File

@ -2,6 +2,7 @@ package huoshan
import (
"errors"
"net/url"
"strings"
"time"
@ -86,6 +87,11 @@ func MakeImage(aiConf *ai.AIConfig, conf ai.ImageConfig) (ai.ImageResult, error)
if conf.Sref > 0 {
data["ref_ip_weight"] = conf.Sref
}
} else if strings.Contains(conf.Model, ":anime_") {
// 动漫模型
if conf.Sref > 0 {
data["strength"] = conf.Sref
}
} else {
// 图生图模型
style_reference_args := map[string]any{"binary_data_index": 0}
@ -125,3 +131,111 @@ func MakeImage(aiConf *ai.AIConfig, conf ai.ImageConfig) (ai.ImageResult, error)
UsedTime: t2,
}, nil
}
func Edit(aiConf *ai.AIConfig, from string, conf map[string]any) (ai.StringResult, error) {
action := u.String(conf["action"])
c := getVisualClient(aiConf)
t1 := time.Now().UnixMilli()
switch action {
case "EmotionPortrait":
// 修改表情
req := map[string]any{"req_key": "emotion_portrait", "return_url": true}
for k, v := range conf {
if k != "action" {
req[k] = v
}
}
if strings.Contains(from, "://") {
req["image_urls"] = []string{from}
} else {
req["binary_data_base64"] = []string{from}
}
resp, status, err := c.EmotionPortrait(req)
if err != nil {
return ai.StringResult{}, err
}
if status != 200 {
return ai.StringResult{}, errors.New(u.String(resp.Message))
}
result := resp.Data.ImageUrls[0]
return ai.StringResult{
Result: result,
UsedTime: time.Now().UnixMilli() - t1,
}, nil
case "HumanSegment":
// 抠出人像
req := url.Values{
"refine": {u.String(u.Int(conf["refine"]))},
"return_foreground_image": {u.String(u.Int(conf["return_foreground_image"]))},
}
if strings.Contains(from, "://") {
req["image_url"] = []string{from}
} else {
req["image_base64"] = []string{from}
}
resp, status, err := c.HumanSegment(req)
if err != nil {
return ai.StringResult{}, err
}
if status != 200 {
return ai.StringResult{}, errors.New(u.String(resp.Message))
}
// u.WriteFileBytes("mask.jpg", u.UnBase64(resp.Data.Mask))
// u.WriteFileBytes("body.jpg", u.UnBase64(resp.Data.ForegroundImage))
result := resp.Data.ForegroundImage
if result == "" {
result = resp.Data.Mask
}
return ai.StringResult{
Result: result,
UsedTime: time.Now().UnixMilli() - t1,
}, nil
case "FacePretty":
// 美颜
req := url.Values{
"do_risk": {u.GetUpperName(u.String(u.Bool(conf["do_risk"])))},
"multi_face": {u.String(u.Int(conf["multi_face"]))},
"beauty_level": {u.String(u.Float(conf["beauty_level"]))},
}
if strings.Contains(from, "://") {
req["image_url"] = []string{from}
} else {
req["image_base64"] = []string{from}
}
resp, status, err := c.FacePretty(req)
if err != nil {
return ai.StringResult{}, err
}
if status != 200 {
return ai.StringResult{}, errors.New(u.String(resp.Message))
}
return ai.StringResult{
Result: resp.Data.Image,
UsedTime: time.Now().UnixMilli() - t1,
}, nil
case "HairStyle":
// 改变发型
req := url.Values{
"req_key": {"hair_style"},
"return_url": {"true"},
"hair_type": {u.String(conf["hair_type"])},
}
if strings.Contains(from, "://") {
req["image_urls"] = []string{from}
} else {
req["binary_data_base64"] = []string{from}
}
resp, status, err := c.HairStyle(req)
if err != nil {
return ai.StringResult{}, err
}
if status != 200 {
return ai.StringResult{}, errors.New(u.String(resp.Message))
}
return ai.StringResult{
Result: resp.Data.Image,
UsedTime: time.Now().UnixMilli() - t1,
}, nil
}
return ai.StringResult{}, nil
}

10
go.mod
View File

@ -1,13 +1,13 @@
module apigo.cc/ai/huoshan
go 1.22
toolchain go1.22.1
go 1.18
require (
apigo.cc/ai v0.0.1
apigo.cc/ai v0.0.2
apigo.cc/gojs v0.0.4
apigo.cc/gojs/console v0.0.1
apigo.cc/gojs/file v0.0.2
apigo.cc/gojs/util v0.0.3
github.com/ssgo/u v1.7.9
github.com/volcengine/volc-sdk-golang v1.0.182
github.com/volcengine/volcengine-go-sdk v1.0.162
@ -24,7 +24,7 @@ require (
github.com/dlclark/regexp2 v1.11.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-sourcemap/sourcemap v2.1.4+incompatible // indirect
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/ssgo/config v1.7.8 // indirect