diff --git a/bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/dto/TextToImgLoveDto.java b/bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/dto/TextToImgLoveDto.java index db318ba..c591772 100644 --- a/bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/dto/TextToImgLoveDto.java +++ b/bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/dto/TextToImgLoveDto.java @@ -14,6 +14,7 @@ import java.io.Serializable; public class TextToImgLoveDto implements Serializable { + private static final long serialVersionUID = 3028022777339473876L; @ApiModelProperty(value="内容提示词") private String prompt; diff --git a/bnyer-services/bnyer-file/src/main/java/com/bnyer/file/enumeration/AddressEnum.java b/bnyer-services/bnyer-file/src/main/java/com/bnyer/file/enumeration/AddressEnum.java index a64d4cc..96f9fbe 100644 --- a/bnyer-services/bnyer-file/src/main/java/com/bnyer/file/enumeration/AddressEnum.java +++ b/bnyer-services/bnyer-file/src/main/java/com/bnyer/file/enumeration/AddressEnum.java @@ -15,7 +15,8 @@ public enum AddressEnum { FRIEND(4,"friend/"), EMOJI(5,"emoji/"), WATCH(6,"iwatch/"), - SD(7,"sd/"); + SD(7,"sd/"), + LOVE_HEAD(8,"loveHead/"); private Integer businessType; diff --git a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/controller/TiktokMiniController.java b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/controller/TiktokMiniController.java index d111d17..44be988 100644 --- a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/controller/TiktokMiniController.java +++ b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/controller/TiktokMiniController.java @@ -426,6 +426,12 @@ public class TiktokMiniController extends BaseController { return AjaxResult.success(stableDiffusionService.textToImg(param)); } + @ApiOperation(value="情侣头像") + @PostMapping(value = "/textToImgLove") + public AjaxResult textToImgLove(@Validated @RequestBody @ApiParam("情侣头像对象") TextToImgLoveDto param){ + return AjaxResult.success(stableDiffusionService.textToImgLove(param)); + } + @ApiOperation(value="获取绘画者ai绘画分页") @PostMapping(value = "/getAiPaintPage") public TableDataInfo getAiPaintPage(@Validated @RequestBody @ApiParam("ai绘画对象") AiPaintPageDto dto){ diff --git a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/service/StableDiffusionService.java b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/service/StableDiffusionService.java index 85e6a6a..e1ab6e2 100644 --- a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/service/StableDiffusionService.java +++ b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/service/StableDiffusionService.java @@ -4,6 +4,8 @@ import com.bnyer.common.core.dto.TextToImgDto; import com.bnyer.common.core.dto.TextToImgLoveDto; import com.bnyer.common.core.vo.TextToImgVo; +import java.util.List; + public interface StableDiffusionService { @@ -19,7 +21,7 @@ public interface StableDiffusionService { * @param param * @return */ - TextToImgVo textToImgLove(TextToImgLoveDto param); + List textToImgLove(TextToImgLoveDto param); void imgToImg(); diff --git a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/service/impl/StableDiffusionServiceImpl.java b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/service/impl/StableDiffusionServiceImpl.java index 0913795..2821197 100644 --- a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/service/impl/StableDiffusionServiceImpl.java +++ b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/service/impl/StableDiffusionServiceImpl.java @@ -106,24 +106,18 @@ public class StableDiffusionServiceImpl implements StableDiffusionService { AiartClient client = new AiartClient(cred, "ap-guangzhou", clientProfile); // 实例化一个请求对象,每个接口都会对应一个request对象 TextToImageRequest req = new TextToImageRequest(); - req.setPrompt(param.getPrompt()); + + //描述词处理 + //负面提示词 + String negaPrompt = "lowres,bad anatomy,bad hands,text,error,missing fingers,extra digit,fewer digits,cropped,worst quality,low quality,normal quality,jpeg artifacts,signature,watermark,username,blurry,lowres,text, cropped,worst quality,low quality,normal quality,jpeg artifacts,signature, watermark,username,blurry,text,signature,watermark,simple background,toony,dated,low res,line art,flat colors,nsfw,easynegative,naked,nsfw"; + //内容提示词 + String contentPrompt = param.getPrompt(); + //积极预设词 + String activePrompt = "8k,masterpiece,best quality,ultra high res,"; + String resultPrompt = activePrompt + contentPrompt; + req.setPrompt(resultPrompt); //请求风格 - String[] styles1 = new String[0]; - switch (param.getStyleName()) { - case "细腻": - styles1 = new String[]{"110"}; - break; - case "卡通": - styles1 = new String[]{"201"}; - break; - case "科幻": - styles1 = new String[]{"114"}; - break; - case "中国风": - styles1 = new String[]{"101"}; - break; - } - req.setStyles(styles1); + req.setStyles(new String[]{"201"}); //画布大小 ResultConfig resultConfig1 = new ResultConfig(); @@ -160,7 +154,8 @@ public class StableDiffusionServiceImpl implements StableDiffusionService { paint.setPaintId(paintId); paint.setCreateTime(paintTime); paint.setImgUrl(imgStr); - paint.setPrompt(param.getPrompt()); + paint.setPrompt(resultPrompt); + paint.setNegativePrompt(negaPrompt); paint.setModel(param.getModelName()); paint.setStyleName(param.getStyleName()); paint.setHeight(param.getHeight() == null ? "512" : String.valueOf(param.getHeight())); @@ -183,16 +178,24 @@ public class StableDiffusionServiceImpl implements StableDiffusionService { }else{ //采用sd try{ + //内容提示词 + String contentPrompt = param.getPrompt(); + //积极预设词 + String activePrompt = "8k,masterpiece,best quality,ultra high res,"; + String prompt = ""; //判断prompt是否包含中文,中文则翻译,否则跳过 - if(TranslateUtils.isContainChinese(param.getPrompt())){ + if(TranslateUtils.isContainChinese(contentPrompt)){ //调用翻译api - prompt = translate(param.getPrompt()); + prompt = translate(contentPrompt); }else{ - prompt = param.getPrompt(); + prompt = contentPrompt; } - log.info("正向提示词为:【{}】",prompt); + String resultPrompt = activePrompt + prompt; + //lora风格处理 + resultPrompt = resultPrompt + "," + "<" + param.getModelName() +">"; + log.info("正向提示词为:【{}】",resultPrompt); String negaPromptText = ""; //判断反向prompt是否包含中文,中文则翻译,否则跳过 if(StringUtils.isNotBlank(param.getNegativePrompt())){ @@ -206,20 +209,19 @@ public class StableDiffusionServiceImpl implements StableDiffusionService { negaPromptText = param.getNegativePrompt(); } - log.info("反向提示词为:【{}】",negaPromptText); - Map map = new HashMap<>(); - String negaPrompt = "easynegative,nsfw,naked"; + String negaPrompt = "lowres,bad anatomy,bad hands,text,error,missing fingers,extra digit,fewer digits,cropped,worst quality,low quality,normal quality,jpeg artifacts,signature,watermark,username,blurry,lowres,text, cropped,worst quality,low quality,normal quality,jpeg artifacts,signature, watermark,username,blurry,text,signature,watermark,simple background,toony,dated,low res,line art,flat colors,nsfw,easynegative,naked,nsfw"; if(StringUtils.isNotBlank(param.getNegativePrompt())){ negaPrompt = negaPrompt + "," + negaPromptText; } + log.info("反向提示词为:【{}】",negaPrompt); Double eta = param.getEta() == null ? 0 : param.getEta(); Integer batchSize = param.getBatchSize() == null ? 1 :param.getBatchSize(); Integer seed = param.getSeed() == null ? -1 : param.getSeed(); Double cfgScale = param.getCfgScale() == null ? 7 : param.getCfgScale(); Integer steps = param.getSteps() == null ? 25 : param.getSteps(); String samplerIndex = StringUtils.isEmpty(param.getSamplerIndex()) ? "DPM++ 2S a Karras" : param.getSamplerIndex(); - map.put("prompt", prompt); + map.put("prompt", resultPrompt); map.put("restore_faces",false); //面部修复,卡通模型不支持,只适合真人模型 map.put("tiling",false); //生成可平铺的周期性图片 map.put("eta",eta); //取值为0-1 @@ -255,8 +257,8 @@ public class StableDiffusionServiceImpl implements StableDiffusionService { paint.setPaintId(paintId); paint.setCreateTime(paintTime); paint.setImgUrl(imgStr); - paint.setPrompt(param.getPrompt()); - paint.setNegativePrompt(negaPrompt); + paint.setPrompt(prompt); + paint.setNegativePrompt(negaPromptText); paint.setEta(eta); paint.setBatchSize(batchSize); paint.setSeed(seed); @@ -287,7 +289,215 @@ public class StableDiffusionServiceImpl implements StableDiffusionService { } @Override - public TextToImgVo textToImgLove(TextToImgLoveDto param) { + public List textToImgLove(TextToImgLoveDto param) { + //描述词处理 + //内容提示词 + String contentPrompt = param.getPrompt(); + //场景提示词 + String scenePrompt = param.getScenePrompt(); + //内容+场景组合提示词 + String resultPrompt = contentPrompt + "," + scenePrompt; + //积极预设词 + String activePrompt = ",8k,masterpiece,best quality,ultra high res,portrait,"; + //反向提示词 + String negaPrompt = "lowres,bad anatomy,bad hands,text,error,missing fingers,extra digit,fewer digits,cropped,worst quality,low quality,normal quality,jpeg artifacts,signature,watermark,username,blurry,lowres,text, cropped,worst quality,low quality,normal quality,jpeg artifacts,signature, watermark,username,blurry,text,signature,watermark,simple background,toony,dated,low res,line art,flat colors,nsfw,easynegative,nsfw,naked"; + + //配置控制采用sd还是tx文生图 + int button = redisService.getCacheObject(RedisKeyConstant.AI_PAINT_BUTTON); + if(button == AiPaintButtonEnum.TX.getCode()){ + //采用tx + //男头提示词 + String boyHeadStr = "1个男孩" + activePrompt + resultPrompt; + //女头提示词 + String girlHeadStr = "1个女孩" + activePrompt + resultPrompt; + String boyHead = getCoupleHead(boyHeadStr,negaPrompt,param.getPlatform(), param.getPainterId(), param.getPainterName(), param.getStyleName(),button); + log.info("腾讯男头像提示词为:【{}】",boyHead); + String girlHead = getCoupleHead(girlHeadStr,negaPrompt,param.getPlatform(), param.getPainterId(), param.getPainterName(), param.getStyleName(),button); + log.info("腾讯女头像提示词为:【{}】",girlHeadStr); + List imgList = new ArrayList<>(); + imgList.add(boyHead); + imgList.add(girlHead); + return imgList; + }else{ + //采用sd + try{ + //最终结果词 + String prompt = ""; + //判断组合提示词是否包含中文,中文则翻译,否则跳过 + if(TranslateUtils.isContainChinese(resultPrompt)){ + //调用翻译api + prompt = translate(resultPrompt); + }else{ + prompt = resultPrompt; + } + + //男头提示词 + String boyHeadStr = "(1boy)" + activePrompt + prompt; + //女头提示词 + String girlHeadStr = "(1girl)" + activePrompt + prompt; + + String boyHead = getCoupleHead(boyHeadStr,negaPrompt,param.getPlatform(), param.getPainterId(), param.getPainterName(), param.getStyleName(),button); + log.info("sd男头像提示词为:【{}】",boyHeadStr); + String girlHead = getCoupleHead(girlHeadStr,negaPrompt,param.getPlatform(), param.getPainterId(), param.getPainterName(), param.getStyleName(),button); + log.info("sd女头像提示词为:【{}】",girlHeadStr); + List imgList = new ArrayList<>(); + imgList.add(boyHead); + imgList.add(girlHead); + return imgList; + }catch (Exception e){ + log.error("文本翻译错误!"+e); + } + } + return null; + } + + /** + * 情侣头像专用绘制方法 + * @param button sd/tx + * @param headStr 头像描述词 + * @param negaPrompt 反向描述词 + * @param platform 平台 + * @param painterId 绘图者id + * @param painterName 绘图者名称 + * @param styleName 风格名称 + * @return - + */ + private String getCoupleHead(String headStr,String negaPrompt,String platform,Long painterId,String painterName,String styleName,int button){ + + if(button == AiPaintButtonEnum.TX.getCode()){ + //采用腾讯文生图 + try{ + Credential cred = new Credential(tencentTranslateConfig.getSecretId(), tencentTranslateConfig.getSecretKey()); + // 实例化一个http选项,可选的,没有特殊需求可以跳过 + HttpProfile httpProfile = new HttpProfile(); + httpProfile.setEndpoint("aiart.tencentcloudapi.com"); + // 实例化一个client选项,可选的,没有特殊需求可以跳过 + ClientProfile clientProfile = new ClientProfile(); + clientProfile.setHttpProfile(httpProfile); + // 实例化要请求产品的client对象,clientProfile是可选的 + AiartClient client = new AiartClient(cred, "ap-guangzhou", clientProfile); + // 实例化一个请求对象,每个接口都会对应一个request对象 + TextToImageRequest req = new TextToImageRequest(); + + //请求风格 + req.setStyles(new String[]{"201"}); + + //画布大小(头像尺寸固定) + ResultConfig resultConfig1 = new ResultConfig(); + resultConfig1.setResolution("768:768"); + req.setResultConfig(resultConfig1); + + //头像描述词 + req.setPrompt(headStr); + //反向提示词 + req.setNegativePrompt(negaPrompt); + // 返回的resp是一个TextToImageResponse的实例,与请求对象对应 + TextToImageResponse resp = client.TextToImage(req); + String images = resp.getResultImage(); + List list = new ArrayList<>(); + list.add(images); + String paintId = null; + Date paintTime = null; + for (String image : list) { + //base64转file + MultipartFile file = new Base64ToMultipartFileUtils(image, "data:image/png;base64", "file", "tempSDImg"); + //上传图片到七牛云/minio + //String imgStr = remoteFileService.uploadBanner(file).getData(); + //上传图片到七牛云并存入sd文件夹 + String imgStr = remoteFileService.uploadQiNiu(file,8).getData(); + //保存生辰该图片到ai绘画表 + AiPaint paint = new AiPaint(); + paintId = IdUtil.getSnowflakeNextIdStr(); + paintTime = new Date(); + paint.setPaintId(paintId); + paint.setCreateTime(paintTime); + paint.setImgUrl(imgStr); + paint.setPrompt(headStr); + paint.setNegativePrompt(negaPrompt); + paint.setModel("腾讯情侣头像"); + paint.setStyleName(styleName); + paint.setHeight("768"); + paint.setWidth("768"); + paint.setIsShow("1"); + paint.setSource(platform); + paint.setPainterId(painterId); + paint.setPainterName(painterName); + aiPaintService.insert(paint); + return image; + } + } catch (TencentCloudSDKException e) { + log.error("腾讯文生图情侣头像调用错误!"+e.getMessage()); + throw new ServiceException(e.getMessage(),500); + } + }else{ + Map map = new HashMap<>(); + Double eta = 0.0; + Integer batchSize = 1; + Integer seed = -1; + Double cfgScale = 7.0; + Integer steps = 25; + String samplerIndex = "DPM++ SDE Karras"; + + map.put("prompt", headStr); + map.put("restore_faces",false); //面部修复,卡通模型不支持,只适合真人模型 + map.put("tiling",false); //生成可平铺的周期性图片 + map.put("eta",eta); //取值为0-1 + map.put("batch_size",batchSize); //生成图片数可调 + map.put("seed",seed); //种子 + map.put("cfg_scale",cfgScale); //精细度可调 + map.put("steps",steps); //采样步数可调 + map.put("sampler_index",samplerIndex); //采样风格可调 + map.put("negative_prompt",negaPrompt); + map.put("width",512); + map.put("height",512); + log.info("请求stable_diffusion情侣头像请求体为:【{}】", JSON.toJSONString(map)); + try{ + JSONObject jsonObject = restTemplate.postForObject(stableDiffusionConfig.getTxt2ImgUrl(), map, JSONObject.class); + //log.info("请求stable_diffusion响应体的为:【{}】", JSON.toJSONString(jsonObject)); + if(jsonObject != null && jsonObject.getJSONArray("images").size() > 0){ + List images = jsonObject.getJSONArray("images").toJavaList(String.class); + String paintId = null; + Date paintTime = null; + for (String image : images) { + //base64转file + MultipartFile file = new Base64ToMultipartFileUtils(image, "data:image/png;base64", "file", "tempSDImg"); + //上传图片到七牛云/minio + //String imgStr = remoteFileService.uploadBanner(file).getData(); + //上传图片到七牛云并存入情侣头像文件夹 + String imgStr = remoteFileService.uploadQiNiu(file,8).getData(); + //保存生辰该图片到ai绘画表 + AiPaint paint = new AiPaint(); + paintId = IdUtil.getSnowflakeNextIdStr(); + paintTime = new Date(); + paint.setPaintId(paintId); + paint.setCreateTime(paintTime); + paint.setImgUrl(imgStr); + paint.setPrompt(headStr); + paint.setNegativePrompt(negaPrompt); + paint.setEta(eta); + paint.setBatchSize(batchSize); + paint.setSeed(seed); + paint.setCfgScale(cfgScale); + paint.setSteps(steps); + paint.setSamplerIndex(samplerIndex); + paint.setModel("sd情侣头像"); + paint.setStyleName(styleName); + paint.setHeight("512"); + paint.setWidth("512"); + paint.setIsShow("1"); + paint.setSource(platform); + paint.setPainterId(painterId); + paint.setPainterName(painterName); + aiPaintService.insert(paint); + return image; + } + } + }catch (Exception e){ + log.error("情侣头像sd调用失败!,原因为:【{}】",e.getMessage()); + throw new ServiceException("情侣头像绘制失败!",500); + } + return null; + } return null; }