|
|
@@ -185,6 +185,8 @@ class AIGatewayService{
|
|
|
}
|
|
|
|
|
|
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* 图生图
|
|
|
* @param string $prompt 用户输入的文本提示内容
|
|
|
@@ -192,101 +194,156 @@ class AIGatewayService{
|
|
|
* @param array $options 可选参数,可覆盖默认配置
|
|
|
* @return array
|
|
|
*/
|
|
|
- public function imgtoimgGptApi($prompt, $new_image_url, $options = [])
|
|
|
- {
|
|
|
- $imgPath = ROOT_PATH . 'public/' . $new_image_url;
|
|
|
+ public function txt2imgWithControlNet($prompt, $controlImgUrl, $options = []) {
|
|
|
+ $apiUrl = "http://20.0.17.188:45001/sdapi/v1/txt2img";
|
|
|
+ $headers = ['Content-Type: application/json'];
|
|
|
|
|
|
+ $imgPath = ROOT_PATH . 'public/' . ltrim($controlImgUrl, '/');
|
|
|
if (!file_exists($imgPath)) {
|
|
|
- return ['code' => 1, 'msg' => '原图不存在:' . $new_image_url];
|
|
|
+ return ['code' => 1, 'msg' => '图片不存在:' . $controlImgUrl];
|
|
|
}
|
|
|
|
|
|
- // 默认参数配置
|
|
|
- $defaultParams = [
|
|
|
+ $imgData = file_get_contents($imgPath);
|
|
|
+ $base64Img = 'data:image/png;base64,' . base64_encode($imgData);
|
|
|
+
|
|
|
+ $params = [
|
|
|
'prompt' => $prompt,
|
|
|
- 'steps' => 15,
|
|
|
+ 'negative_prompt' => '(deformed, distorted, disfigured:1.3), poorly drawn, bad anatomy',
|
|
|
+ 'steps' => 20,
|
|
|
+ 'sampler_name' => 'DPM++ 2M SDE',
|
|
|
'cfg_scale' => 7,
|
|
|
- 'denoising_strength' => 0.2,
|
|
|
- 'width' => 679,
|
|
|
- 'height' => 862,
|
|
|
- 'resize_mode' => 2,
|
|
|
- 'sampler_name' => 'DPM++ 2M SDE Heun',
|
|
|
- 'seed' => -1, // 使用-1表示随机种子
|
|
|
- 'inpaint_full_res' => true,
|
|
|
- 'inpainting_fill' => 1,
|
|
|
+ 'seed' => -1,
|
|
|
+ 'width' => 1024,
|
|
|
+ 'height' => 1303,
|
|
|
'override_settings' => [
|
|
|
- 'sd_model_checkpoint' => 'realisticVisionV51_v51VAE-inpainting.safetensors [f0d4872d24]',
|
|
|
- 'sd_vae' => 'anything-v4.5.vae.pt',
|
|
|
- 'CLIP_stop_at_last_layers' => 7
|
|
|
+ 'sd_model_checkpoint' => 'realisticVisionV51_v51VAE-inpainting',
|
|
|
+ 'sd_vae' => 'vae-ft-mse-840000-ema-pruned',
|
|
|
+ 'CLIP_stop_at_last_layers' => 2
|
|
|
],
|
|
|
- 'override_settings_restore_afterwards' => true
|
|
|
+ 'clip_skip' => 2,
|
|
|
+ 'alwayson_scripts' => [
|
|
|
+ 'controlnet' => [
|
|
|
+ 'args' => [[
|
|
|
+ 'enabled' => true,
|
|
|
+ 'input_image' => $base64Img,
|
|
|
+ 'module' => 'inpaint_only+lama',
|
|
|
+ 'model' => 'control_v11p_sd15_inpaint_fp16 [be8bc0ed]',
|
|
|
+ 'weight' => 1,
|
|
|
+ 'resize_mode' => 'Resize and Fill',
|
|
|
+ 'pixel_perfect' => false,
|
|
|
+ 'control_mode' => 'ControlNet is more important',
|
|
|
+ 'starting_control_step' => 0,
|
|
|
+ 'ending_control_step' => 1
|
|
|
+ ]]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
];
|
|
|
|
|
|
- // 合并用户自定义选项
|
|
|
- $params = array_merge($defaultParams, $options);
|
|
|
-
|
|
|
- // 原图 base64 编码
|
|
|
- $imgData = file_get_contents($imgPath);
|
|
|
- $base64Img = base64_encode($imgData);
|
|
|
- $params['init_images'] = ['data:image/png;base64,' . $base64Img];
|
|
|
-
|
|
|
- $apiUrl = "http://20.0.17.188:45001/sdapi/v1/img2img";
|
|
|
- $headers = ['Content-Type: application/json'];
|
|
|
+ if (!empty($options)) {
|
|
|
+ $params = array_merge($params, $options);
|
|
|
+ }
|
|
|
|
|
|
$ch = curl_init();
|
|
|
curl_setopt($ch, CURLOPT_URL, $apiUrl);
|
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
curl_setopt($ch, CURLOPT_POST, true);
|
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
|
|
- curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
|
|
|
- curl_setopt($ch, CURLOPT_TIMEOUT, 90);
|
|
|
+ curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params, JSON_UNESCAPED_UNICODE));
|
|
|
+ curl_setopt($ch, CURLOPT_TIMEOUT, 180);
|
|
|
|
|
|
$response = curl_exec($ch);
|
|
|
-
|
|
|
- if (curl_errno($ch)) {
|
|
|
- $error = curl_error($ch);
|
|
|
- curl_close($ch);
|
|
|
- return ['code' => 1, 'msg' => '请求失败:' . $error];
|
|
|
- }
|
|
|
-
|
|
|
- $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
|
+ $error = curl_error($ch);
|
|
|
curl_close($ch);
|
|
|
|
|
|
- if ($httpCode !== 200) {
|
|
|
- return ['code' => 1, 'msg' => 'API请求失败,HTTP状态码:' . $httpCode];
|
|
|
+ if ($error) {
|
|
|
+ return ['code' => 1, 'msg' => '请求失败:' . $error];
|
|
|
}
|
|
|
|
|
|
$data = json_decode($response, true);
|
|
|
- if (json_last_error() !== JSON_ERROR_NONE) {
|
|
|
- return ['code' => 1, 'msg' => 'API返回数据解析失败:' . json_last_error_msg()];
|
|
|
- }
|
|
|
-
|
|
|
if (!isset($data['images'][0])) {
|
|
|
- $errorMsg = $data['error'] ?? $data['message'] ?? '未知错误';
|
|
|
- return ['code' => 1, 'msg' => 'API未返回图像数据:' . $errorMsg];
|
|
|
+ return ['code' => 1, 'msg' => '接口未返回图像数据'];
|
|
|
}
|
|
|
|
|
|
return [
|
|
|
'code' => 0,
|
|
|
- 'msg' => '图像生成成功',
|
|
|
+ 'msg' => '成功',
|
|
|
'data' => [
|
|
|
- 'url' => $data['images'][0]
|
|
|
+ 'base64' => $data['images'][0],
|
|
|
+ 'info' => $data['info'] ?? ''
|
|
|
]
|
|
|
];
|
|
|
}
|
|
|
|
|
|
|
|
|
- /**
|
|
|
- * 图片高清放大
|
|
|
- * @param string $imageRelPath 原图相对路径(相对 public)
|
|
|
- * @param array $options 可选参数,可覆盖默认放大配置
|
|
|
- * @return array
|
|
|
- */
|
|
|
- /**
|
|
|
- * 图片高清放大(不保存,返回 base64)
|
|
|
- * @param string $imageRelPath 原图相对路径(相对 public)
|
|
|
- * @param array $options 可选参数
|
|
|
- * @return array
|
|
|
- */
|
|
|
+
|
|
|
+ // 第一阶段:图生图
|
|
|
+ public function upscaleWithImg2Img($prompt, $imgPath)
|
|
|
+ {
|
|
|
+ if (!file_exists($imgPath)) {
|
|
|
+ return ['code' => 1, 'msg' => '原图不存在:' . $imgPath];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取原始图像尺寸
|
|
|
+ [$origWidth, $origHeight] = getimagesize($imgPath);
|
|
|
+ if (!$origWidth || !$origHeight) {
|
|
|
+ return ['code' => 1, 'msg' => '无法识别图片尺寸'];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 按2倍尺寸计算目标大小
|
|
|
+ $targetWidth = $origWidth * 2;
|
|
|
+ $targetHeight = $origHeight * 2;
|
|
|
+
|
|
|
+ // 编码图像为 base64
|
|
|
+ $imgData = file_get_contents($imgPath);
|
|
|
+ $base64Img = 'data:image/png;base64,' . base64_encode($imgData);
|
|
|
+
|
|
|
+ // 构造参数
|
|
|
+ $params = [
|
|
|
+ 'init_images' => [$base64Img],
|
|
|
+ 'prompt' => $prompt,
|
|
|
+ 'steps' => 20,
|
|
|
+ 'sampler_name' => 'DPM++ 2M SDE Heun',
|
|
|
+ 'cfg_scale' => 7,
|
|
|
+ 'seed' => 1669863506,
|
|
|
+ 'width' => $targetWidth,
|
|
|
+ 'height' => $targetHeight,
|
|
|
+ 'denoising_strength' => 0.2,
|
|
|
+ 'clip_skip' => 2,
|
|
|
+ 'override_settings' => [
|
|
|
+ 'sd_model_checkpoint' => 'realisticVisionV51_v51VAE-inpainting.safetensors [f0d4872d24]',
|
|
|
+ 'sd_vae' => 'vae-ft-mse-840000-ema-pruned.safetensors',
|
|
|
+ 'CLIP_stop_at_last_layers' => 2
|
|
|
+ ],
|
|
|
+ 'override_settings_restore_afterwards' => true
|
|
|
+ ];
|
|
|
+
|
|
|
+ $apiUrl = "http://20.0.17.188:45001/sdapi/v1/img2img";
|
|
|
+ $headers = ['Content-Type: application/json'];
|
|
|
+
|
|
|
+ // 发起请求
|
|
|
+ $ch = curl_init();
|
|
|
+ curl_setopt_array($ch, [
|
|
|
+ CURLOPT_URL => $apiUrl,
|
|
|
+ CURLOPT_RETURNTRANSFER => true,
|
|
|
+ CURLOPT_POST => true,
|
|
|
+ CURLOPT_HTTPHEADER => $headers,
|
|
|
+ CURLOPT_POSTFIELDS => json_encode($params),
|
|
|
+ CURLOPT_TIMEOUT => 180
|
|
|
+ ]);
|
|
|
+
|
|
|
+ $response = curl_exec($ch);
|
|
|
+ $error = curl_error($ch);
|
|
|
+ curl_close($ch);
|
|
|
+
|
|
|
+ if ($error) return ['code' => 1, 'msg' => '图生图请求失败:' . $error];
|
|
|
+
|
|
|
+ $data = json_decode($response, true);
|
|
|
+ if (!isset($data['images'][0])) return ['code' => 1, 'msg' => '图生图接口未返回图像'];
|
|
|
+
|
|
|
+ return ['code' => 0, 'data' => ['base64' => $data['images'][0]]];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 第二阶段:高清超分
|
|
|
public function imgtogqGptApi($imageRelPath, $options = [])
|
|
|
{
|
|
|
$imgPath = ROOT_PATH . 'public/' . $imageRelPath;
|
|
|
@@ -301,7 +358,7 @@ class AIGatewayService{
|
|
|
'gfpgan_visibility' => 0,
|
|
|
'codeformer_visibility' => 0,
|
|
|
'codeformer_weight' => 0,
|
|
|
- 'upscaling_resize' => 2.45,
|
|
|
+ 'upscaling_resize' => 1.62,
|
|
|
'upscaling_crop' => true,
|
|
|
'upscaler_1' => 'R-ESRGAN 4x+ Anime6B',
|
|
|
'upscaler_2' => 'None',
|