OpenAI: Images, 指定エリアの編集

OpenAI: Images, 指定エリアの編集

translate OpenAI: Images, Edit Specific Area

画像内の「透過エリア」を、指示文(PROMPT)にもとづいて補完します。デフォルトでは 1024×1024 の画像が生成されます。編集されるエリアを別ファイル(透過エリアを含む同サイズ画像)で指定することも可能です。なお元画像は4MB未満の正方形画像でなければなりません。また、一度に作成できる数は最大で10です。

Auto Step icon
Configs for this Auto Step
AuthzConfU1
U1: HTTP認証設定を選択してください(Secret API Key @トークン直接指定) *
StrConfA0
A0: リクエスト PROMPT(指示文)をセットしてください *#{EL}
SelectConfA1
A1: オリジナル画像が格納されているファイル型データ項目を選択してください *
SelectConfA1b
A1b: 編集エリアを別画像で指定する場合、当該画像が格納されているファイル型データ項目を選択してください
SelectConfB1
B1: 自動生成された画像が格納されるファイル型データ項目を選択してください(更新)
StrConfU2
U2: OpenAI Organization ID をセットしてください(”org-xxxx”)#{EL}
StrConfU3
U3: 監視や検知のための End-User ID をセットしてください(”user123456″)#{EL}
StrConfA2
A2: 画像の生成数をセットしてください(1~10)#{EL}
StrConfA3
A3: 画像サイズをセットしてください(”256×256″, “512×512”, or “1024×1024″)#{EL}
SelectConfB2
B2: 自動生成された画像が格納されるファイル型データ項目を選択してください(追加)
StrConfC1
C1: 別名保存したい場合、新しいファイル名をセットしてください (改行区切り)#{EL}
Script (click to open)
// GraalJS Script (engine type: 2)

//////// START "main()" /////////////////////////////////////////////////////////////////

main();
function main(){ 

////// == Config Retrieving / 工程コンフィグの参照 ==
const strAuthzSetting   = configs.get( "AuthzConfU1" );       /// REQUIRED
  engine.log( " AutomatedTask Config: Authz Setting: " + strAuthzSetting );
const strOrgId          = configs.get( "StrConfU2" );         // NotRequired
  engine.log( " AutomatedTask Config: OpenAI-Organization: " + strOrgId );
const strEndUserId      = configs.get( "StrConfU3" ) !== "" ? // NotRequired
                          configs.get( "StrConfU3" ) :
                          "m" + processInstance.getProcessModelInfoId().toString(); // (default)
  engine.log( " AutomatedTask Config: End User IDs: " + strEndUserId );

const strPrompt         = configs.get( "StrConfA0" );         /// REQUIRED
  if( strPrompt       === "" ){
    throw new Error( "\n AutomatedTask ConfigError:" +
                     " Config {A0: Prompt} must be non-empty \n" );
  }
const filesPocketOriginal = configs.getObject( "SelectConfA1" ); /// REQUIRED
  let filesOriginal     = engine.findData( filesPocketOriginal ); // java.util.ArrayList
  if( filesOriginal   === null ){
    throw new Error( "\n AutomatedTask ConfigError:" +
                     " Config {A1: OriginalFile} must be non-empty \n" );
  }
  engine.log( " AutomatedTask Config: #of Original Files: " + filesOriginal.size() );
  engine.log( " AutomatedTask Config: Original Image File: " + filesOriginal.get(0).getName() );
const filesPocketMask   = configs.getObject( "SelectConfA1b" ); // NotRequired
  let filesMask         = filesPocketMask !== null ?
                          engine.findData( filesPocketMask ) : null;
  if( filesMask       === null ){
    engine.log( " AutomatedTask Config: No Mask file used" );
  } else {
    engine.log( " AutomatedTask Config: Mask Image File: " + filesMask.get(0).getName() );
  }

const strGenerate       = configs.get( "StrConfA2" );         // NotRequired
const numGenerate       = isNaN( parseInt(strGenerate,10) ) ? 1 : parseInt(strGenerate,10);
const strSize           = configs.get( "StrConfA3" ) !== "" ? // NotRequired
                          configs.get( "StrConfA3" ) : "1024x1024"; // (default)

const filesPocketUpdate = configs.getObject( "SelectConfB1" ); // NotRequired
  let filesUpdate       = new java.util.ArrayList();
const filesPocketAppend = configs.getObject( "SelectConfB2" ); // NotRequired
  let filesAppend       = new java.util.ArrayList();
  if ( filesPocketAppend !== null ) {
    if ( engine.findData( filesPocketAppend ) !== null ) {
      filesAppend       = engine.findData( filesPocketAppend ); // java.util.ArrayList
      engine.log( " AutomatedTask FilesArray {B2}: " +
                  filesAppend.size() + " files" );
    }
  }
const strFileNames      = configs.get( "StrConfC1" );           // NotRequired
const arrFileNames      = strFileNames === "" ?
                          [] : strFileNames.split( '\n' );



////// == Data Retrieving / ワークフローデータの参照 ==
// (Nothing. Retrieved via Expression Language in Config Retrieving)



////// == Calculating / 演算 ==

//// OpenAI API > Documentation > API REFERENCE > IMAGES > Create image edit
//// https://platform.openai.com/docs/api-reference/images/create-edit

/// prepare request1
let request1Uri = "https://api.openai.com/v1/images/edits";
let request1 = httpClient.begin(); // HttpRequestWrapper
    request1 = request1.authSetting( strAuthzSetting ); // with "Authorization: Bearer XX"
    if ( strOrgId !== "" ){
      request1 = request1.header( "OpenAI-Organization", strOrgId );
    }

/// prepare multipart/form-data
    request1 = request1.multipart ( "prompt",          strPrompt );
    request1 = request1.multipart ( "n",               numGenerate.toString() );
    request1 = request1.multipart ( "size",            strSize );
    request1 = request1.multipart ( "response_format", "url" );
    request1 = request1.multipart ( "user",            strEndUserId );
    request1 = request1.multipart ( "image",           filesOriginal.get(0) );
    if ( filesMask !== null ){
      request1 = request1.multipart ( "mask",          filesMask.get(0) );
    }

/// try request1
const response1     = request1.post( request1Uri ); // HttpResponseWrapper
engine.log( " AutomatedTask ApiRequest1 Start: " + request1Uri );
const response1Code = response1.getStatusCode() + ""; // JavaNum to string
const response1Body = response1.getResponseAsString();
engine.log( " AutomatedTask ApiResponse1 Status: " + response1Code );
if( response1Code !== "200"){
  throw new Error( "\n AutomatedTask UnexpectedResponseError: " +
                    response1Code + "\n" + response1Body + "\n" );
}

engine.log( response1Body ); // debug★★★
/// parse response1
/* engine.log( response1Body ); // debug
{
  "created": 1683701883,
  "data": [
    {
      "url": "https://oaidalleapiprodscus.blob.core.windows.net/private/org-sWMNKIpK"
    },
    {
      "url": "https://oaidalleapiprodscus.blob.core.windows.net/private/org-sWMNKIpK"
    },
    {
      "url": "https://oaidalleapiprodscus.blob.core.windows.net/private/org-sWMNKIpK"
    },
    {
      "url": "https://oaidalleapiprodscus.blob.core.windows.net/private/org-sWMNK..."
    }
  ]
}
*/
const response1Obj = JSON.parse( response1Body );
engine.log( " AutomatedTask OpenAI #created: " + response1Obj.created );

for ( let i = 0; i < response1Obj.data.length; i++ ) {

  /// prepare request2
  let request2Uri = response1Obj.data[i].url;
  let request2 = httpClient.begin(); // HttpRequestWrapper

  /// try request2i
  const response2     = request2.get( request2Uri ); // HttpResponseWrapper
  engine.log( " AutomatedTask ApiRequest2 Start: " + request2Uri );
  const response2Code = response2.getStatusCode() + ""; // JavaNum to string
  engine.log( " AutomatedTask ApiResponse2 Status: " + response2Code );
  if( response2Code !== "200"){
    throw new Error( "\n AutomatedTask UnexpectedResponseError: " +
                      response2Code + "\n" + response2.getResponseAsString() + "\n" );
  }

  /*   // debug
  let jarrHeaders = response2.getHeaderNames();
  for ( let j = 0; j < jarrHeaders.size() - 0 ; j++ ) {
    engine.log( " " + jarrHeaders.get(j) );
  }

  Content-Length
  Content-Type
  Content-MD5
  Last-Modified
  Accept-Ranges
  ETag
  Server
  x-ms-request-id
  x-ms-version
  x-ms-creation-time
  x-ms-lease-status
  x-ms-lease-state
  x-ms-blob-type
  Content-Disposition
  x-ms-server-encrypted
  Date
  */

  /// save file
  let strName = arrFileNames[i] ?? "";
  if ( strName === "" ) {
    strName = processInstance.getProcessInstanceId().toString() +
            "-" + i + ".png";
  }
  const qfileTmp = new com.questetra.bpms.core.event.scripttask.NewQfile(
    strName, response2.getContentType(), response2.getResponse()
  );
  // NewQfile ( stringFileName, stringContentType, ByteArray )

  filesUpdate.add( qfileTmp );
  filesAppend.add( qfileTmp );

}



////// == Data Updating / ワークフローデータへの代入 ==

if( filesPocketUpdate !== null ){
  engine.setData( filesPocketUpdate, filesUpdate );
}
if( filesPocketAppend !== null ){
  engine.setData( filesPocketAppend, filesAppend );
}

} //////// END "main()" /////////////////////////////////////////////////////////////////


/*
Notes:
- If you place this "Automated Step" in the Workflow diagram, the request will be automatically sent every time the process token arrives.
    - A request is automatically sent to the OpenAI API server. (REST API)
    - The response from the OpenAI API server is automatically parsed.
    - You can incorporate "AI assistance" into your business processes.
- This "Automated Step" accesses the image generation engine "DALL-E 2" Model. (as of 2023)
    - The maximum number of images that can be generated is 10.
- Automate various AI image editing.
    - Correcting photos with imperfections
    - Change facial expressions of character illustrations

APPENDIX
- To activate a Workflow App that includes this Automated Step, "HTTP Authz Setting" is required
    - Obtain a "Secret API Key" in advance.
    - Set the key as the communication token in "Token Fixed Value"
- If multiple images are stored, the first file will be considered the original image.
    - The file must be a valid PNG file. (RGB mode, RGBA mode)
    - The file must be a perfect square.
- To specify the area to be edited in another file (Mask Image)
    - Must be the same size
        - e.g. `"Invalid input mask - mask size must match image size 1200x1200, got 1024x1024 instead."`
    - Must contain transparent areas
        - Transparent PNG Examples
        - square1024-top-transparent.png
        - square1024-bottom-transparent.png
        - square1024-right-transparent.png
        - square1024-left-transparent.png
        - square1024-center-transparent.png

Notes-ja:
- この[自動工程]をワークフロー図に配置すれば、案件が到達する度にリクエストが自動送信されます。
    - OpenAI API サーバに対してリクエストが自動送出されます。(REST API通信)
    - OpenAI API サーバからのレスポンスが自動保存解析されます。
    - "AI による支援" を業務プロセスに組み込むことが出来ます。
- この[自動工程]は、画像生成エンジン "DALL-E 2" Model にアクセスします。(2023現在)
    - 一度に生成できる画像は、最大で10個です。
- さまざまAI画像編集を自動化できます。
    - 写り込みがある写真の補正
    - キャラクターイラストの表情変更

APPENDIX-ja
- この[アドオン自動工程]を含むワークフローアプリを運用するには[HTTP 認証設定]が必要です。
    - あらかじめ "Secret API Key" を取得しておいてください。
    - "Secret API Key" を通信トークンとしてセットします。[トークン直接指定]
- 複数画像が格納されている場合、第1番目のファイルをオリジナル画像とみなします。
    - 当該ファイルは、PNG形式でなければなりません。(RGBモード、RGBAモード)
    - 当該ファイルは、完全な正方形でなければなりません。
- 編集領域を別ファイル(マスク画像)で指定する場合:
    - 同じサイズでなければなりません
        - e.g. `"Invalid input mask - mask size must match image size 1200x1200, got 1024x1024 instead."`
    - 透明な領域を含まなければなりません
        - 透過 PNG サンプル
        - square1024-top-transparent.png
        - square1024-bottom-transparent.png
        - square1024-right-transparent.png
        - square1024-left-transparent.png
        - square1024-center-transparent.png
*/

Download

warning 自由改変可能な JavaScript (ECMAScript) コードです。いかなる保証もありません。
(アドオン自動工程のインストールは Professional editionでのみ可能です)

Notes

  • この[自動工程]をワークフロー図に配置すれば、案件が到達する度にリクエストが自動送信されます。
    • OpenAI API サーバに対してリクエストが自動送出されます。(REST API通信)
    • OpenAI API サーバからのレスポンスが自動保存解析されます。
    • “AI による支援” を業務プロセスに組み込むことが出来ます。
  • この[自動工程]は、画像生成エンジン “DALL-E 2” Model にアクセスします。(2023現在)
    • 一度に生成できる画像は、最大で10個です。
  • さまざまAI画像編集を自動化できます。
    • 写り込みがある写真の補正
    • キャラクターイラストの表情変更

Capture

画像内の「透過エリア」を、指示文(PROMPT)にもとづいて補完します。デフォルトでは 1024x1024 の画像が生成されます。編集されるエリアを別ファイル(透過エリアを含む同サイズ画像)で指定することも可能です。なお元画像は4MB未満の正方形画像でなければなりません。また、一度に作成できる数は最大で10です。

Appendix

  • この[アドオン自動工程]を含むワークフローアプリを運用するには[HTTP 認証設定]が必要です。
    • あらかじめ “Secret API Key” を取得しておいてください。
    • “Secret API Key” を通信トークンとしてセットします。[トークン直接指定]
  • 複数画像が格納されている場合、第1番目のファイルをオリジナル画像とみなします。
    • 当該ファイルは、PNG形式でなければなりません。(RGBモード、RGBAモード)
    • 当該ファイルは、完全な正方形でなければなりません。
  • 編集領域を別ファイル(マスク画像)で指定する場合:

See Also

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

%d人のブロガーが「いいね」をつけました。