Moví la herramienta de dibujo AI a mi propia aplicación, y es de código abierto y gratuito

prefacio

Como todos los demás, también estoy pensando en cómo usar las herramientas Ai existentes para mejorar de manera efectiva la actividad de la aplicación y diversificar los servicios internos. Todos han probado mucho en ChatGPT, así que planeo comenzar con la herramienta de dibujo Ai.

Pero ahora Midjourney empieza a cobrar, 30 cuchillos al mes sigue siendo bastante caro, así que me di por vencido (después de todo, soy pobre). Entonces recordé el Scribble Diffusion que usaba antes. Solo necesita dibujar dos bocetos para generar imágenes de alta calidad. La experiencia es buena y es gratis.

Scribble Diffusion es un servicio en línea simple que usa IA para transformar bocetos en bruto en imágenes refinadas, cada una diferente (y libre de dolores de cabeza por derechos de autor). En pocas palabras, solo necesitamos "dibujar un boceto con un pincel, esperar un momento después de ingresar la descripción", y luego se generará una pintura para usted. Esta pintura se puede generar varias veces, y el resultado de cada generación también es muy diferente.

La habilidad de Scribble Diffusion es probablemente así (la izquierda está dibujada por mí y la derecha está dibujada por TA)

una foto de pastizales con nubes

el sol poniéndose detrás de las montañas

un gatito encantador

Descubrí que la capacidad de Scribble Diffusion para dibujar es muy inesperada, y puedes definir diferentes estilos de fotos (como fotos, pinturas al óleo, bocetos, etc.) (después de todo, funciona de forma inmediata y no requiere ninguna configuración). Los amigos que no entienden la tecnología de los contenedores de programas pequeños pueden prestar atención a FinClip , mPaaS y otros productos).

Después de investigar en el sitio web oficial , descubrí que los elementos del sitio web oficial son muy simples. Debido a esto, creo que hay varios pasos para mover "Scribble Diffusion" al subprograma FinClip :

  1. Use el lienzo para realizar el tablero de dibujo y puede dibujar en el subprograma;
  2. Proporcione un cuadro de entrada y un botón generado, que pueden complementar la descripción de la imagen y el botón generado;
  3. Obtenga el enlace de la imagen generada para mostrar

Use applets para implementar blocs de dibujo

Podemos usar un pequeño programa para implementar un tablero de dibujo y usar la etiqueta del lienzo para implementar la función de pincel. Los usuarios pueden dibujar en el tablero de dibujo o elegir borrar el tablero de dibujo.

Aquí hay un código de muestra:

<!--画布区域-->
<view class="canvas_area">
    <canvas id="myCanvas" canvas-id="myCanvas" class="myCanvas"
        disable-scroll="false"
        bindtouchstart="touchStart"
        bindtouchmove="touchMove"
        bindtouchend="touchEnd">
    </canvas>
</view>
<view class="clearBtn" bindtap="reset">
  清空画板
</view>
复制代码
Page({
  data: {
    isProcessing: false,
    prompt: '',
    scribble: null,
    pen : 2, //画笔粗细默认值
    color : '#000000', // 画笔颜色默认值
    result: null,
    text: ''
  },
  startX: 0, //保存X坐标轴变量
  startY: 0, //保存X坐标轴变量

  onLoad(params) {
    wx.createSelectorQuery().select('#myCanvas').context((res) => {
      this.context = res.context
    }).exec()
  },

  //手指触摸动作开始
  touchStart: function (e) {
      //得到触摸点的坐标
      this.startX = e.changedTouches[0].x
      this.startY = e.changedTouches[0].y
      // this.context = wx.createContext()

      this.context.setStrokeStyle(this.data.color)
      this.context.setLineWidth(this.data.pen)
      this.context.setLineCap('round') // 让线条圆润 
      this.context.beginPath()
  },
  //手指触摸后移动
  touchMove: function (e) {
      var startX1 = e.changedTouches[0].x
      var startY1 = e.changedTouches[0].y

      this.context.moveTo(this.startX, this.startY)
      this.context.lineTo(startX1, startY1)
      this.context.stroke()

      this.startX = startX1;
      this.startY = startY1;
        
      
      //只是一个记录方法调用的容器,用于生成记录绘制行为的actions数组。context跟<canvas/>不存在对应关系,一个context生成画布的绘制动作数组可以应用于多个<canvas/>
      wx.drawCanvas({
         canvasId: 'myCanvas',
         reserve: true,
         actions: this.context.getActions() // 获取绘图动作数组
      })
  },
  //手指触摸动作结束
  touchEnd: function () {
    var imageData =  wx.canvasGetImageData({
      canvasId: 'myCanvas',
      height: 250,
      width: 250,
      x: 0,
      y: 0,
      success(res){
        return res.data
      }
    })
  },
  //清除画板
  reset: function(){
    this.context.clearRect(0, 0, 400, 400);
    this.context.draw(true)
  }
})
复制代码

Proporcione el cuadro de entrada y el botón generar

Necesitamos proporcionar un cuadro de entrada de entrada para que el usuario ingrese el mensaje; al mismo tiempo, debemos proporcionar un botón, que activará un evento de respuesta cuando se haga clic, generará una imagen del contenido del lienzo y enviará la entrada del mensaje. como un parámetro para el servidor para la generación de imágenes.

Aquí hay un código de muestra:

<!-- 输入框 -->
<view class="imageDes"> 
  <view class="formInput"> 
    <input class="input" type="text" name="go"  placeholder="用关键词描述画的内容" bindinput="update"/>
  </view>
</view>
复制代码
Page({
  ... 省略上述代码
  // 更新表单提交按钮状态
  update(e){
    this.setData({
      prompt : e.detail.value
    })
  },
})
复制代码

Obtenga el enlace de la imagen generada y muéstrelo

Cuando el usuario haga clic en el botón Generar imagen, enviaremos el contenido del lienzo y el aviso ingresado por el usuario como parámetros al servidor para la generación de imágenes. El servidor devolverá el enlace de la imagen generada y debemos mostrárselo al usuario.

En el código de muestra a continuación, nuestro servidor envía una solicitud POST, luego analiza los datos JSON devueltos, obtiene el enlace de la imagen y lo agrega a la página. El usuario puede ver la imagen generada.

<!-- 绘图结果 -->
<view class="result" wx:if="{{result}}">
  <view class="resultBox">
    <view class="content">
      <image class="content" src="{{result}}" mode="aspectFit" /> 
    </view>
    <view class="download">
      <view class="btn" bindtap="download">
        下载
      </view>
    </view>
  </view>
</view>
复制代码
Page({
  ... 省略上述代码
  async getCanvasImage() {
    return new Promise((resolve, reject) => {
      wx.canvasToTempFilePath({
        x: 0,
        y: 0,
        width: 250,
        height: 250,
        destWidth: 250,
        destHeight: 250,
        canvasId: 'myCanvas',
        success(res) {
          console.log(res.tempFilePath)
          resolve(res.tempFilePath)
        },
        fail(err) {
          console.log(err)
        }
      })
    })
  },
  async upload(image) {
    return new Promise((resolve) => {
      wx.uploadFile({
        url: 'xxxxxx',
        filePath: image,
        name: 'file',
        success (res){
          const data = JSON.parse(res.data)
          resolve(data.url)
        },
        fail(err){
          console.log('上传失败')
          console.log(err)
        }
      })
    })
  },
	async sleep(time) {
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve()
      }, time)
    })
  },
  async handleSubmit(e) {
    if (!this.data.prompt) {
      return
    }
    wx.showLoading({
      title: '生成中',
    })
    try {
      const prompt = this.data.prompt
      const image = await this.getCanvasImage()
      this.setData({
        error: null,
        isProcessing: true
      });
      const url = await this.upload(image)
      console.log('图片', url)
      const body = {
        prompt: prompt,
        image: url,
      };
      const response = await my_fetch.fetch( {
        url: "https://scribblediffusion.com/api/predictions",
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        params: JSON.stringify(body),
      });
      let prediction = response.data;
      console.log('预测', prediction)

      if (response.statusCode !== 201) {
        wx.showToast({
          title: '生成失败',
          duration: 2000
        })
        this.setData({
          error: '生成失败'
        });
        return;
      }
      while (
        prediction.status !== "succeeded" &&
        prediction.status !== "failed"
      ) {
        console.log(prediction.status)
        await this.sleep(500);
        const response = await my_fetch.fetch({
          url:"https://scribblediffusion.com/api/predictions/" + prediction.id,
        });
        prediction = response.data;
        if (response.statusCode !== 200) {
          this.setData({
            error: prediction.detail
          });
          return;
        }
      }
      if (Array.isArray(prediction.output) && prediction.output.length > 1) {
        wx.hideLoading()
        this.setData({
          isProcessing: false,
          result: prediction.output[1]
        });
      } else {
        wx.hideLoading()
        wx.showToast({
          title: '生成失败',
          duration: 2000
        })
        this.setData({
          isProcessing: false,
          error: '生成失败'
        })
      } 
    } catch (error) {
      wx.hideLoading()
      console.log(error)
      wx.showToast({
        title: '生成失败',
        duration: 2000
      }) 
    }
  },
})
复制代码

¡Después de generar el applet, cargue el applet a través del fondo de administración para obtener la herramienta de dibujo ai en la aplicación!

Por supuesto, si tiene más ideas extrañas sobre Scribble Diffusion y desea ponerlas en práctica, el desarrollador también ha abierto los archivos del proyecto, por lo que puede probarlos ~

Supongo que te gusta

Origin juejin.im/post/7221333917079863351
Recomendado
Clasificación