如何申请 Midjourney API ,看这篇文章就够了

news2024/9/20 22:32:25

Midjourney Imagine API 的申请与应用

Midjourney,这一杰出的 AI 绘图工具,凭借输入几个关键字,便能在短短一两分钟内生成极为精美的图像,展现出令人惊叹的创作能力。它以独特的绘画技术在行业中独树一帜,现今在各个领域都得到了广泛运用,影响力愈发显著。

本文将详细阐述如何申请和使用 Midjourney API 的 Imagine 操作,通过该工具,我们得以轻松地根据文字描述生成所需图像。

注册试用链接

点击此处注册试用链接

申请步骤

欲使用 Midjourney Imagine API,首先请访问 Midjourney Imagine API 页,点击「Acquire」按钮以获取所需的凭证:

若尚未登录或注册,则会自动跳转至登录页面,邀请您完成注册或登录,成功后便会返回此页面。

首次申请时,您将获得一定的免费额度,可无偿使用该 API。

基本使用

接下来,您可以在界面中填写相关内容,具体如图所示:

在首次利用此接口时,至少需要填写两个内容:一是 authorization,可以从下拉列表中直选;二是 prompt,即我们希望生成的图像描述内容,建议使用英文,这样生成的图像效果精准且优雅。例如,我们可以使用 Lamborghini speeds inside a volcano,代表希望构建一幅描绘兰博基尼在火山中飞驰的画面。

同时,您会注意到右侧会有对应的调用代码生成,您可以直接复制该代码并运行,或者直接点击「Try」按钮以进行测试。

调用后,返回结果如以下所示:

{
  "image_url": "https://midjourney.cdn.acedata.cloud/attachments/1233387694839697411/1234197197067915365/36rgqit64j90qptsxnyq_Lamborghini_speeds_inside_a_volcano_id0494_f47263b6-ff92-44a3-88ee-51cf0e706aae.png?ex=662fdb36&is=662e89b6&hm=ca9be54907726937ed02517a13466bef2afb2825b7cda4b313de56a3c3310d0d&width=1024&height=1024",
  "image_width": 1024,
  "image_height": 1024,
  "image_id": "1234197197067915365",
  "raw_image_url": "https://midjourney.cdn.acedata.cloud/attachments/1233387694839697411/1234197197067915365/36rgqit64j90qptsxnyq_Lamborghini_speeds_inside_a_volcano_id0494_f47263b6-ff92-44a3-88ee-51cf0e706aae.png?ex=662fdb36&is=662e89b6&hm=ca9be54907726937ed02517a13466bef2afb2825b7cda4b313de56a3c3310d0d&",
  "raw_image_width": 2048,
  "raw_image_height": 2048,
  "progress": 100,
  "actions": [
    "upscale1",
    "upscale2",
    "upscale3",
    "upscale4",
    "reroll",
    "variation1",
    "variation2",
    "variation3",
    "variation4"
  ],
  "task_id": "1bae3bec-3ac4-4180-a148-74ee6cb68b98",
  "success": true
}

返回结果包含多个字段,具体解释如下:

  • task_id:本图像生成任务的唯一标识符,用于标记此项操作。
  • image_id:图像的唯一标识,需用于下次对图片的变动操作。
  • image_url:缩略图的 URL,单击可直接查看生成效果。
  • image_width:缩略图的像素宽度。
  • image_height:缩略图的像素高度。
  • raw_image_url:原始图的 URL,与缩略图的内容相同,但分辨率更高,加载速度会相对较慢。
  • raw_image_width:原图的像素宽度。
  • raw_image_height:原图的像素高度。
  • actions:可对生成图片进行的后续处理操作列表。此处总共列出 8 项,其中 upscale 代表放大,variation 表示变更。因此,upscale1 表示对左上角第一张图片进行放大操作,variation3 则代表依据左下角第三幅图像进行变化操作。

访问 image_url 或者 raw_image_url 提供的链接,您将看到如图所示的结果。

在此,生成了一个 2x2 的预览图,至此,首轮 API 调用已完成。

图像放大与变更

接下来,让我们尝试对当前生成的图像进行进一步操作。比如,我们觉得右上角的第二幅图还不错,但想对此进行微调,那么可以进一步将 action 设定为 variation2,并同样传入 image_id

此时返回结果如下:

{
  "image_url": "https://midjourney.cdn.acedata.cloud/attachments/1233387694839697411/1234201336543969401/36rgqit64j90qptsxnyq_Lamborghini_speeds_inside_a_volcano_id0494_10dc56a7-ec16-4bac-878e-2338f2ae5f5d.png?ex=662fdf10&is=662e8d90&hm=9aec96bca35ae20b6f9ab536101b9c4ea255eb6216cbf7000ac554937da071f3&width=1024&height=1024",
  "image_width": 1024,
  "image_height": 1024,
  "image_id": "1234201336543969401",
  "raw_image_url": "https://midjourney.cdn.acedata.cloud/attachments/1233387694839697411/1234201336543969401/36rgqit64j90qptsxnyq_Lamborghini_speeds_inside_a_volcano_id0494_10dc56a7-ec16-4bac-878e-2338f2ae5f5d.png?ex=662fdf10&is=662e8d90&hm=9aec96bca35ae20b6f9ab536101b9c4ea255eb6216cbf7000ac554937da071f3&",
  "raw_image_width": 2048,
  "raw_image_height": 2048,
  "progress": 100,
  "actions": [
    "upscale1",
    "upscale2",
    "upscale3",
    "upscale4",
    "reroll",
    "variation1",
    "variation2",
    "variation3",
    "variation4"
  ],
  "task_id": "f4961620-1104-409f-9dc1-ba3ed15c2f4d",
  "success": true
}

点击 image_url ,您将看到更新后的图像如下:

可以察觉,我们在上一次的右上角图像上,进一步得到了四张相似的新图。

在此,我们可以选择其中一张进行精细放大操作。如果选择了第四张,则可以将 action 传入 upscale4,并再次提供当前图像的 image_id

需要注意的是,upscale 操作相较于 variation 在 Midjourney 的耗时上会更短一些。

返回结果如下:

{
  "image_url": "https://midjourney.cdn.acedata.cloud/attachments/1233387694839697411/1234202545208033400/36rgqit64j90qptsxnyq_Lamborghini_speeds_inside_a_volcano_id0494_34edc3f5-2bd0-4f5b-a372-03270b02289b.png?ex=662fe031&is=662e8eb1&hm=f8006c4d33a03dfd027dffe4eb46ab0d113a4910aef07497f0b335c8998b7858&width=512&height=512",
  "image_width": 512,
  "image_height": 512,
  "image_id": "1234202545208033400",
  "raw_image_url": "https://midjourney.cdn.acedata.cloud/attachments/1233387694839697411/1234202545208033400/36rgqit64j90qptsxnyq_Lamborghini_speeds_inside_a_volcano_id0494_34edc3f5-2bd0-4f5b-a372-03270b02289b.png?ex=662fe031&is=662e8eb1&hm=f8006c4d33a03dfd027dffe4eb46ab0d113a4910aef07497f0b335c8998b7858&",
  "raw_image_width": 1024,
  "raw_image_height": 1024,
  "progress": 100,
  "actions": [
    "upscale_2x",
    "upscale_4x",
    "variation_subtle",
    "variation_strong",
    "zoom_out_2x",
    "zoom_out_1_5x",
    "pan_left",
    "pan_right",
    "pan_up",
    "pan_down"
  ],
  "task_id": "03f62b17-a6f1-4c8e-9b4d-1fc7bd5b1180",
  "success": true
}

在此,image_url 表达的图像如图所示:

这便是我们成功获得了一幅兰博基尼的照片。

注意到 actions 中还包含了进一步可进行的操作,具体如下:

  • upscale_2x:将画面放大两倍,生成更高分辨率的图像。
  • upscale_4x:将画面放大四倍,创造出四倍高清的效果。
  • zoom_out_2x:对画面进行二倍缩小,将周围区域进行填充。
  • zoom_out_1_5x:将画面缩小至1.5倍,同样填充周围区域。
  • pan_left:对画面进行向左偏移。
  • pan_right:对画面进行向右偏移。
  • pan_up:对画面进行向上移动。
  • pan_down:对画面进行向下移动。

您可以循序渐进按照上述指令进行条件变换操作。

图像改写(垫图)

此 API 还支持图像改写,亦称为垫图。通过提供一张图片的 URL 以及需要改写的描述文字,API 能够返回改写后的图像。

请注意:输入的图片 URL 必须是纯图片形式,不能是网页中的图片展示,否则无法进行图像改写。推荐使用图床上传图片以获取有效 URL。

例如,假设我们这有一张公路落日的图,地图边上点缀着树木和楼房,如下所示:

假如我们希望在此基础上改写成一个海滩场景,且在路边停放一辆汽车,我们可以构造如下的提示内容:

https://cdn.acedata.cloud/v014oc.png an illustration of a car parked on the beach --iw 2

可以看到,我们的提示以 HTTPS 开头的图片链接为起点,紧接一个空格,然后添加描述内容。在此还应用了一些高级参数,如 —iw 2 用以调整图像的权重。

将如上内容整合并传入 prompt 字段,具体如图所示:

输出结果如下:

{
  "image_url": "https://midjourney.cdn.acedata.cloud/attachments/1234427310434947145/1234539663515975690/atmateosa5693_An_illustration_of_a_car_parked_on_the_beach_id26_cc8650ec-7e4b-4685-8911-78172430d8a7.png?ex=66311a28&is=662fc8a8&hm=c39707a1f22bc7f12874060ea6ed58ba37c188139ccc9a13c61ed9f37e66ea74&width=1456&height=816",
  "image_width": 1456,
  "image_height": 816,
  "image_id": "1234539663515975690",
  "raw_image_url": "https://midjourney.cdn.acedata.cloud/attachments/1234427310434947145/1234539663515975690/atmateosa5693_An_illustration_of_a_car_parked_on_the_beach_id26_cc8650ec-7e4b-4685-8911-78172430d8a7.png?ex=66311a28&is=662fc8a8&hm=c39707a1f22bc7f12874060ea6ed58ba37c188139ccc9a13c61ed9f37e66ea74&",
  "raw_image_width": 2912,
  "raw_image_height": 1632,
  "progress": 100,
  "actions": [
    "upscale1",
    "upscale2",
    "upscale3",
    "upscale4",
    "reroll",
    "variation1",
    "variation2",
    "variation3",
    "variation4"
  ],
  "task_id": "24a79e8b-a79d-471a-aef7-089dc0627ee8",
  "success": true
}

此时,我们得到了生成的图片,如下所示:

从中可以看出,在保留原图整体风格与构图的基础上,整个场景已成功转变为海滩旁,同时路上也驶来了汽车,这便是 Prompt with Image 的奇妙应用。

图像融合

此 API 同样支持图像融合,透过传入多幅图片,实现各不同的融合效果。

假如我们这有两张图,一张为一只玩具熊,另一张则是电锯,各自如图所示:

现在假设我们想将两者融合,使得玩具熊手持电锯,该如何实现?

可以构建如下的提示:

https://img-blog.csdnimg.cn/img_convert/9cae0b08d833d9b707f0876da8641783.png https://img-blog.csdnimg.cn/img_convert/f71e1ecda7743fccc7ae749411f8b475.png The bear is holding the chainsaw --iw 2

与 Image with Prompt 类似,图像的 URL 被放置在提示开头,用空格分隔,之后再添加具体的文字描述,整体传递给 prompt 参数即可,运行效果如下:

{
  "image_url": "https://midjourney.cdn.acedata.cloud/attachments/1234291876639674388/1234547236830973972/kcisok_The_bear_is_holding_the_chainsaw_id8873344_ad605bc4-ba19-4807-b94f-367dab672f7a.png?ex=66312136&is=662fcfb6&hm=0fb1e2261c9a30b04de9da9b23b7562eb73677f1bbda1fae52c7243b12d25aac&width=1024&height=1024",
  "image_width": 1024,
  "image_height": 1024,
  "image_id": "1234547236830973972",
  "raw_image_url": "https://midjourney.cdn.acedata.cloud/attachments/1234291876639674388/1234547236830973972/kcisok_The_bear_is_holding_the_chainsaw_id8873344_ad605bc4-ba19-4807-b94f-367dab672f7a.png?ex=66312136&is=662fcfb6&hm=0fb1e2261c9a30b04de9da9b23b7562eb73677f1bbda1fae52c7243b12d25aac&",
  "raw_image_width": 2048,
  "raw_image_height": 2048,
  "progress": 100,
  "actions": [
    "upscale1",
    "upscale2",
    "upscale3",
    "upscale4",
    "reroll",
    "variation1",
    "variation2",
    "variation3",
    "variation4"
  ],
  "task_id": "891f2645-ee15-4c7b-ac24-d98163c8e57e",
  "success": true
}

最终,我们将得到如下结果:

证明我们成功实现了图片融合!

请注意,图片融合最多支持 5 个图片 URL 作为输入,也即最多支持 5 张图片的融合,输入格式与之前一致。

局部变换

该 API 亦支持图像的局部绘制,但仅限于通过上文内容生成的图像。我们可以传入某个生成图像的唯一 ID、局部重绘的行为参数 action 以及指定重绘区域的掩码 mask,以便在该掩码区域进行重绘。

假设我们当前拥有一张有关猫咪的图像:

如果我们希望对这只猫的脸进行重绘,如何操作?

首先,需获取该区域的掩码 mask。此 mask 是通过灰度图像进行 Base64 编码生成的。以下提供获取掩码的代码示例:

Python 获取掩码示例代码:

import sys
import os
from PySide6.QtWidgets import *
from PySide6.QtGui import QPainter, QMouseEvent, QPen, QColor, QImage
from PySide6.QtCore import Qt, QPoint

class DrawingWidget(QWidget):
    def __init__(self, imagePath):
        super().__init__()
        self.setAttribute(Qt.WA_StaticContents)
        self.background_image = QImage(imagePath)
        imageSize = self.background_image.size() * 0.8
        self.setFixedSize(imageSize)
        self.foreground_image = QImage(self.size(), QImage.Format_ARGB32)
        self.foreground_image.fill(Qt.transparent)
        self.drawing = False
        self.lastPoint = QPoint()
        self.pen_color = QColor(255, 255, 255, 255)
        self.pen_size = 50

    def set_pen_size(self, size):
        self.pen_size = size

    def mousePressEvent(self, event: QMouseEvent):
        if event.button() == Qt.LeftButton:
            self.drawing = True
            self.lastPoint = event.pos()

    def mouseMoveEvent(self, event: QMouseEvent):
        if event.buttons() & Qt.LeftButton and self.drawing:
            painter = QPainter(self.foreground_image)
            painter.setRenderHint(QPainter.Antialiasing, True)
            pen = QPen(self.pen_color, self.pen_size, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
            painter.setPen(pen)
            painter.drawLine(self.lastPoint, event.pos())
            self.lastPoint = event.pos()
            self.update()

    def mouseReleaseEvent(self, event: QMouseEvent):
        if event.button() == Qt.LeftButton and self.drawing:
            self.drawing = False

    def paintEvent(self, event):
        canvasPainter = QPainter(self)
        canvasPainter.drawImage(self.rect(), self.background_image, self.background_image.rect())
        canvasPainter.drawImage(self.rect(), self.foreground_image, self.foreground_image.rect())

    def save_image(self, path):
        self.foreground_image.save(path)

class MainWindow(QDialog):
    def __init__(self, imagePath):
        super().__init__()
        self.setWindowTitle("mask tool")
        self.drawing_widget = DrawingWidget(imagePath)
        self.currentPath = os.getcwd().replace("\\", "/")
        self.tempPath = self.currentPath + "/temp.jpg"
        self.projectPath = ""
        self.setDone = False

    def init_ui(self):
        layout = QVBoxLayout()
        layout.addWidget(self.drawing_widget)
        controls_layout = QHBoxLayout()
        size_label = QLabel("pen size:")
        controls_layout.addWidget(size_label)
        self.size_slider = QSlider(Qt.Horizontal)
        self.size_slider.setMinimum(100)
        self.size_slider.setMaximum(400)
        self.size_slider.setValue(400)
        self.size_slider.valueChanged.connect(self.update_pen_size)
        controls_layout.addWidget(self.size_slider)
        self.lineEdit_addPromp = QLineEdit()
        layout.addWidget(self.lineEdit_addPromp)
        save_button = QPushButton("   Start partial redrawing   ")
        save_button.clicked.connect(self.save_image)
        controls_layout.addWidget(save_button)
        dont_button = QPushButton("   Cancel partial redraw   ")
        dont_button.clicked.connect(self.dont_image)
        controls_layout.addWidget(dont_button)
        layout.addLayout(controls_layout)
        self.setLayout(layout)

    def update_pen_size(self):
        size = self.size_slider.value()
        self.drawing_widget.set_pen_size(size)

    def save_image(self):
        tempImage = self.currentPath + "/temp.jpg"
        self.drawing_widget.save_image(self.tempPath)
        self.prompt = self.lineEdit_addPromp.text()
        self.setDone = True
        self.close()

    def dont_image(self):
        self.setDone = False
        self.close()

    def closeEvent(self, event):
        if self.setDone:
            pass
        else:
            self.setDone = False
        event.accept()


if __name__ == '__main__':
    imagePath = "test.png"
    app = QApplication(sys.argv)
    mainWindow = MainWindow(imagePath)
    mainWindow.init_ui()
    mainWindow.exec()

上述代码可以产生掩码图像。此过程中需注意掩码图片的尺寸必须与原始图片一致,而掩码图中白色区域即为待重绘的部分。下面展示猫咪图像的掩码图片与原图对比:

原图片:

掩码图片:

最后,我们还需将掩码图片转换为基于 Base64 的编码,接下来提供转换代码:

Python 转换 Base64 示例代码:

import cv2
import base64

image_path = 'temp.jpg'
gray_image = cv2.imread(image_path)
_, buffer = cv2.imencode('.jpg', gray_image)
base64_encoded = base64.b64encode(buffer).decode('utf-8')
with open('grayscale_image_base64.txt', 'w') as f:
    f.write(base64_encoded)

print("success!")

请注意:上述 Python 代码描述了 mask 的生成过程,如需将其嵌入产品中,请根据原理编写相应语言的代码。

通过以上代码,我们得到了所需重绘的掩码 mask 接下来需将参数 action 设为 variation_region ,并提供生成图像的 ID image_id(参考上文获取此参数),以及对应的掩码 mask。其他参数详细信息如下:

  • action:图像处理行为,此处设为 variation_region,意为进行局部重绘。
  • prompt:局部重绘的描述词(可选)。
  • image_id:图像的唯一标识,用以便利局部重绘。
  • mask:图像掩码区域的 base64 编码(由上文指定的 image_id 所给出)。

根据上述规则设定参数,prompt 参数为非必填项,但为方便对比,可将其设为 A cute cat,参数配置如下图示:

代码示例

如您所见,页面右侧自动生成了多种语言的代码,如下图所示:

部分代码示例如下:

CURL
curl -X POST 'https://api.acedata.cloud/midjourney/imagine' \
-H 'accept: application/json' \
-H 'authorization: Bearer {token}' \
-H 'content-type: application/json' \
-d '{
  "prompt": "A cute cat ",
  "action": "variation_region",
  "image_id": "1265875488702726144",
  "mask": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAMEBgUGBgYFBgYGBwkIBgcJBwYGCAsICQoKCgoKBggLDAsKDAkKCgr/2wBDAQICAgICAgUDAwUKBwYHCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgr/wAARCAGaAZoDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD+f+iiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAP/Z"
}'
Python
import requests

url = "https://api.acedata.cloud/midjourney/imagine"

headers = {
    "accept": "application/json",
    "authorization": "Bearer {token}",
    "content-type": "application/json"
}

payload = {
    "prompt": "A cute cat ",
    "action": "variation_region",
    "image_id": "1265875488702726144",
    "mask": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAMEBgUGBgYFBgYGBwkIBgcJBwYGCAsICQoKCgoKBggLDAsKDAkKCgr/2wBDAQICAgICAgUDAwUKBwYHCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgr/wAARCAGaAZoDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD+f+iiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAP/Z"
}'

响应示例

请求成功时,API 将返回处理后的图像结果。例如:

{
  "image_url": "https://platform.cdn.acedata.cloud/midjourney/6c9450d8-1c22-4f85-a527-e7a7bfb4a61b.png?imageMogr2/thumbnail/!50p",
  "image_width": 1024,
  "image_height": 1024,
  "actions": [
    "upscale1",
    "upscale2",
    "upscale3",
    "upscale4",
    "reroll",
    "variation1",
    "variation2",
    "variation3",
    "variation4"
  ],
  "raw_image_url": "https://platform.cdn.acedata.cloud/midjourney/6c9450d8-1c22-4f85-a527-e7a7bfb4a61b.png",
  "raw_image_width": 2048,
  "raw_image_height": 2048,
  "progress": 100,
  "image_id": "1265876571323891712",
  "task_id": "6c9450d8-1c22-4f85-a527-e7a7bfb4a61b",
  "success": true
}

返回结果显示掩码区域的图像已完成重绘,输出信息与上文一致,结果如图所示:

由此可见,我们成功对所生成的图像的自定义区域进行了局部重绘。

异步回调

由于 Midjourney 生成图像需要一定的时间,本 API 也设计为长等待模式。然而在某些场景中,长时间等待可能会带来高昂的资源费用,因此本 API 提供了异步 Webhook 回调方式。当图像生成成功或失败时,其结果均会通过 HTTP 请求发送至指定的 Webhook 回调 URL。接收到的结果可进行进一步处理。

接下来,将演示具体的调用流程。

首先,Webhook 回调应是一个能接收 HTTP 请求的服务,开发者需替换为自建的 HTTP 服务器 URL。为便于演示,使用一个公开的 Webhook 示例网站 https://webhook.site/,打开后即可得到一个 Webhook URL,如下图所示:

将此 URL 复制即可作为 Webhook 使用,示例为 https://webhook.site/995d0a91-d737-40a7-a3b9-5baf68ed924c。

接下来,我们可设置字段 callback_url 赋值为上述 Webhook URL,并填入 prompt,具体如图所示:

点击测试后,会立即收到一条包含 task_id 的响应,用于标识当前生成任务的 ID,如下所示:

稍作等待,待图片生成完毕,您将发现 Webhook URL 收到了一条 HTTP 请求,具体如下:

这便是当前任务的结果,内容如下:

{
  "success": true,
  "task_id": "f6e39eaf-652a-4bf5-a15c-79d8b143b80a",
  "image_url": "https://midjourney.cdn.acedata.cloud/attachments/1234291876639674388/1234551030549839932/kcisok_A_cat_sitting_on_a_table_id2724480_591c5c85-ec80-42ab-9fe5-9adfbed192e4.png?ex=663124be&is=662fd33e&hm=da725eb74aae375d60beec38b4cd26c5a7b373b1662f222ff838a8ea6fd5e798&width=1024&height=1024",
  "image_width": 1024,
  "image_height": 1024,
  "image_id": "1234551030549839932",
  "raw_image_url": "https://midjourney.cdn.acedata.cloud/attachments/1234291876639674388/1234551030549839932/kcisok_A_cat_sitting_on_a_table_id2724480_591c5c85-ec80-42ab-9fe5-9adfbed192e4.png?ex=663124be&is=662fd33e&hm=da725eb74aae375d60beec38b4cd26c5a7b373b1662f222ff838a8ea6fd5e798&",
  "raw_image_width": 2048,
  "raw_image_height": 2048,
  "progress": 100,
  "actions": [
    "upscale1",
    "upscale2",
    "upscale3",
    "upscale4",
    "reroll",
    "variation1",
    "variation2",
    "variation3",
    "variation4"
  ]
}

其中 success 字段指示任务执行状态,若成功,则将返回 actionsimage_idimage_url 字段,信息与前述一致,另外还有 task_id 用于标识当前任务,以便于将 Webhook 结果与最初 API 请求关联。

若图像生成时出现错误,Webhook URL 则会接收到如下内容:

{
  "success": false,
  "task_id": "7ba0feaf-d20b-4c22-a35a-31ec30fc7715",
  "error": {
    "code": "bad_request",
    "message": "Unrecognized argument(s): `-c`, `x`"
  }
}

在此,success 字段将显示为 false,并附带 error.codeerror.message 字段,描述出具体错误信息,Webhook 服务器将根据返回结果进行处理。

流式输出

Midjourney 在图像生成过程中是具有进度反馈的,初始时图像模糊,随着多轮迭代逐渐变得清晰,最终得到了完整的图像。

因此,图像的生成过程大致可分为三个阶段:「发送命令」->「开始生图(多次迭代逐渐清晰)」->「生图完毕」。

若未开启流式输出,则 API 从请求到返回结果整个过程会被捕捉,包括「发送命令」到「生图完毕」。由于 Midjourney 本身生成图像速度较慢,因此整个过程往往需要一分钟或更长时间。

为提供更好的用户体验,本 API 支持流式输出,意即在「开始生图」时便开始返回结果,每当绘制进度有变化,就会通过流式方式输出,直到生图过程结束。

若希望流式返回响应,可以在请求头中将 accept 参数修改为 application/x-ndjson,但是调用代码需要相应更改以支持流式响应。

Python 示例代码:

import requests

url = 'https://api.acedata.cloud/midjourney/imagine'
headers = {
    'content-type': 'application/json',
    'accept': 'application/x-ndjson',
    'authorization': 'Bearer {token}'
}
body = {
    "prompt": "a beautiful cat --v 6"
}
r = requests.post(url, headers=headers, json=body, stream=True)
for line in r.iter_lines():
    print(line.decode())

运行结果类似于:

{"image_url":"https://midjourney.cdn.acedata.cloud/attachments/1234291876639674388/1234558451443699803/eae94f0f-0ba5-4b3c-9bad-59fb33ac2cbc_grid_0.webp?ex=66312ba7&is=662fda27&hm=4625d5f12158bffc07c4faaf6ce75af6f1396122f148b33b91f3e20b48fecc8b&width=256&height=256","image_width":256,"image_height":256,"image_id":"1234558451443699803","raw_image_url":"https://midjourney.cdn.acedata.cloud/attachments/1234291876639674388/1234558451443699803/eae94f0f-0ba5-4b3c-9bad-59fb33ac2cbc_grid_0.webp?ex=66312ba7&is=662fda27&hm=4625d5f12158bffc07c4faaf6ce75af6f1396122f148b33b91f3e20b48fecc8b&","raw_image_width":512,"raw_image_height":512,"progress":35,"actions":[],"task_id":"49589d2c-b6b3-4fbf-9f82-93068509c76f","success":true}
{"image_url":"https://midjourney.cdn.acedata.cloud/attachments/1234291876639674388/1234558458595115149/eae94f0f-0ba5-4b3c-9bad-59fb33ac2cbc_grid_0.webp?ex=66312ba9&is=662fda29&hm=9af53fa645127131a88dfbb3930add7abda710c12a3d6c30c457d6a067b36bab&width=256&height=256","image_width":256,"image_height":256,"image_id":"1234558458595115149","raw_image_url":"https://midjourney.cdn.acedata.cloud/attachments/1234291876639674388/1234558458595115149/eae94f0f-0ba5-4b3c-9bad-59fb33ac2cbc_grid_0.webp?ex=66312ba9&is=662fda29&hm=9af53fa645127131a88dfbb3930add7abda710c12a3d6c30c457d6a067b36bab&","raw_image_width":512,"raw_image_height":512,"progress":75,"actions":[],"task_id":"49589d2c-b6b3-4fbf-9f82-93068509c76f","success":true}
{"image_url":"https://midjourney.cdn.acedata.cloud/attachments/1234291876639674388/1234558483408490566/kcisok_A_landscape_painting_of_a_beautiful_sunset_id5963392_eae94f0f-0ba5-4b3c-9bad-59fb33ac2cbc.png?ex=66312baf&is=662fda2f&hm=185ea8f130806bf8bd96911bd251808455fd65596edcdb459f9b3cfd7860387c&width=1024&height=1024","image_width":1024,"image_height":1024,"image_id":"1234558483408490566","raw_image_url":"https://midjourney.cdn.acedata.cloud/attachments/1234291876639674388/1234558483408490566/kcisok_A_landscape_painting_of_a_beautiful_sunset_id5963392_eae94f0f-0ba5-4b3c-9bad-59fb33ac2cbc.png?ex=66312baf&is=662fda2f&hm=185ea8f130806bf8bd96911bd251808455fd65596edcdb459f9b3cfd7860387c&","raw_image_width":2048,"raw_image_height":2048,"progress":100,"actions":["upscale1","upscale2","upscale3","upscale4","reroll","variation1","variation2","variation3","variation4"],"task_id":"49589d2c-b6b3-4fbf-9f82-93068509c76f","success":true}

启用流式输出后,返回结果会逐行输出 JSON 数据。

在 Node.js 环境中,可以根据如下代码实现:

const axios = require("axios");

const url = "https://api.acedata.cloud/midjourney/imagine";
const headers = {
  "content-type": "application/json",
  accept: "application/x-ndjson",
  authorization: "Bearer {token}",
};
const body = {
  prompt: "a beautiful cat --v 6",
  action: "generate",
};

axios
  .post(url, body, { headers: headers, responseType: "stream" })
  .then((response) => {
    console.log(response.status);
    response.data.on("data", (chunk) => {
      console.log(chunk.toString());
    });
  })
  .catch((error) => {
    console.error(error);
  });

这样的示例运行所产生的结果均相似。

请留意,流式输出结果中的 progress 字段表示当前生成进度,数值范围为 0 到 100。如需,可在页面上展示此信息。

注意:在生成未完全完成时,actions 字段会为空,意味着无法对中间图像进行后续处理。生成完成后,生成过程中的 image_url 将被自动销毁。

此外,您也可以通过在请求头指定 accept=application/x-ndjson 和在请求体中添加 callback_url,将流式结果与异步回调结合,使得多个流式结果的 POST 请求都能成功达到 callback_url。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2072505.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

墨刀基础篇(一) :6.常用组件(动态组件)

一:动态组件 动态组件是除了文件和矩形之外最重要的一个组件。文本和矩形是一切组件的基础,而动态组件是复杂组件的根本。动态组件就是可以拥有多个状态,每个状态可以放不同的内容,每个状态之间可以互相切换,每个状态…

springboot系列--springboot前置知识

一、spring相关知识 一、spring能干什么 二、spring生态 spring生态覆盖了:web开发、数据访问、安全控制、分布式、消息服务、移动开发、批处理等等。 官网链接:Spring | Home 二、springboot相关知识 一、springboot作用 Spring Boot makes it easy …

Ansys Rocky在电池制造行业应用

Ansys Rocky在电池制造行业应用 对于电池电极制造的理解 干湿混合应用 砑光应用 微尺度电极干燥应用 更多应用 材料生产 电极和电池生产

prolog 基础 - 关系和属性

首先进入环境; 看一下一开始的提示符是 ?- ,现在可以用write语句输出一些东西; 根据资料,在prolog中, 两个对象之间的关系,使用括号表示。比如,jack的朋友是peter,写成friend(ja…

论文笔记:Large Language Models are Zero-Shot Next LocationPredictors

1 intro 下一个地点预测(NL)包括基于个体历史访问位置来预测其未来的位置。 NL对于应对各种社会挑战至关重要,包括交通管理和优化、疾病传播控制以及灾害响应管理NL 问题已经通过使用马尔可夫模型、基于模式的方法以及最近的深度学习&#x…

突破传统,GCOM80-2NET的创新性边缘计算方式

GCOM80-2NET边缘计算网关,突破传统Modbus协议仅能进行数据读采的限制,直接在设备终端进行复杂的数据点运算,减少冗余数据传输,释放软件人员针对不同Modbus设备协议解析的时间。 GCOM80-2NET,是ZLG致远电子推出的一款高…

OpManager Plus简单说明以及在Linux下的安装

目录 1 简介2 安装2.1 Linux下安装 1 简介 OpManager Plus 属于ManageEngine,是一款商业软件。 ManageEngine OpManager是一款全面的网络监视软件,可为网络管理员提供集成控制台,用于管理路由器,防火墙,服务器&#x…

免费个人网站怎么建立

一、选择免费网站建设平台 有许多免费的网站建设平台可供选择,如WordPress.com 、Wix、Weebly等。这些平台提供了易于使用的界面和模板,能够帮助用户快速创建个人网站博客网站 _ 网址大全 _ 博科趣 - 第2页博客网站大全,博客网址导航,个人独立博客,个人博…

Vue3项目开发——新闻发布管理系统(二)

文章目录 五、项目的目录调整六、系统整体路由设计开发1、系统整体路由分析2、路由配置2.1路由代码解析2.2路由信息设计2.3系统路由信息汇总2.4路由信息配置2.5路由对应Vue组件框架3系统效果五、项目的目录调整 默认生成的src目录结构如下: 这个结构不能满足我们的开发需求,…

Python测试框架之—— pytest介绍与示例

Pytest是一个功能强大且易于使用的Python测试框架,它提供了丰富的功能和灵活的用法,使得编写和运行测试变得简单而高效。 一、Pytest的特点 简单灵活:Pytest的语法简洁清晰,容易上手,并且支持复杂的测试场景。自动发…

为什么制造企业数字化转型需要MES管理系统

制造企业数字化转型需要MES管理系统,这主要源于MES管理系统在提升生产效率、优化资源配置、加强质量控制以及实现数据驱动决策等方面的显著优势。以下是具体的原因分析: 1. 提升生产效率 实时数据采集与分析:MES管理系统能够实时收集生产过程…

【(逆向)PE64是什么意思?】

PE64 是指 64 位的可移植可执行(Portable Executable)文件格式。在 Windows 操作系统中,PE 文件是一种常见的可执行文件格式。 在逆向工程中,判断一个 PE 文件是否为 64 位通常需要检查其特定的结构和字段。例如,可以…

利用 UrlClickEvents 深入研究网络钓鱼活动

在 Microsoft 365 Defender 中发现了一个新的高级搜索表:UrlClickEvents 图 1 – UrlClickEvents 表 在撰写本文时,此表尚未出现在每个 Office 365 租户中,官方文档中也不包含有关它的信息。快速查看它包含的事件表明,它记录了用户从 Office 应用程序(例如 Outlook 和 Te…

中仕公考怎么样?事业编备考技巧!

距离2024年下半年事业编考试还有两个月的时间,现在开始准备还能抓住机会!事业编考试一定要了解: 一、事业编招考流程 发布公告→注册报名→选岗→交报名费→报名确认→打印准考证→笔试→调剂→面试→体检→录用。 二、事业编报考地址 1.省人事考试网…

VUE3+nest.js前后端部署-服务器linux中部署Node.js环境

一.安装分布式版本管理系统Git (Alibaba Cloud Linux 3/2、CentOS 7.x) sudo yum install git -y 二.使用Git将NVM的源码克隆到本地的~/.nvm目录下,并检查最新版本。 git clone https://gitee.com/mirrors/nvm.git ~/.nvm && cd ~/.nvm && gi…

34 增加系统调用(3)

首先是 在GDT中添加 系统调用的内容: 然后是汇编中实现 syscall_hander 然后是使用C语言函数 实现在屏幕上显示字符。 然后是在 任务中调用这个函数。 然后 sys_show 去调用 系统调用。 在进行系统调用前需要 保存现场。 系统调用之后需要 释放现场。 为了保证在系统…

前端宝典十八:高频算法排序之冒泡、插入、选择、归并和快速

前言 十大经典排序算法的 时间复杂度与空间复杂度 比较。 名词解释: n:数据规模;k:桶的个数;In-place: 占用常数内存,不占用额外内存;Out-place: 占用额外内存。 本文主要探讨高频算法排序中…

docker安装ES(Elasticsearch)的IK分词器

大家可以先看我的Docker中部署Kibana: “Docker中部署Kibana:步骤与指南“-CSDN博客 其实这几篇博文都是有关系的,希望大家学有所成。 问题:命令中有一个unzip没有安装,需要先安装一下,安装命令&#xf…

计算机毕业设计 高校学术交流平台 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…

前端宝典十七:算法之复杂度、链表、队列、栈的代码实现

引文 从本文开始主要探讨前端的算法,这一篇主要涉及: 时间复杂度&空间复杂度;链表;队列;栈; 希望通过学习能掌握好 具体代码时间复杂度&空间复杂度的算法;链表、队列、栈的JavaScri…