support some Edit Image
This commit is contained in:
		
							parent
							
								
									db308fe42b
								
							
						
					
					
						commit
						1c4932d005
					
				@ -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"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										17
									
								
								ai_test.js
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								ai_test.js
									
									
									
									
									
								
							@ -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')
 | 
			
		||||
 | 
			
		||||
@ -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,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										96
									
								
								default.yml
									
									
									
									
									
								
							
							
						
						
									
										96
									
								
								default.yml
									
									
									
									
									
								
							@ -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
									
									
									
									
									
								
							
							
						
						
									
										114
									
								
								gc.go
									
									
									
									
									
								
							@ -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
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								go.mod
									
									
									
									
									
								
							@ -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
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user