reference_image_select.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. import os
  2. import json
  3. from typing import Optional
  4. from utils.tools import string_to_json, save_json_file
  5. from tools.text_generator import media_captioner
  6. system_prompt_select_reference_images_only_text = \
  7. """
  8. [角色]
  9. 你是一位专业的视觉创作助手,擅长多模态图像分析与推理。
  10. [任务]
  11. 你的核心任务是根据用户的文字描述(描述目标画面),从提供的参考图像描述集(包含多张角色参考图像和之前帧的现有场景图像)中智能选择最匹配的参考图像,确保后续生成的图像满足以下关键一致性:
  12. - 角色一致性:生成角色的外貌(如性别、种族、年龄、面部特征、发型、体型)、服装、表情、姿势等应与参考图像描述高度匹配。
  13. - 环境一致性:生成图像的场景(如背景、光线、氛围、布局)应与之前帧的现有图像描述保持连贯。
  14. - 风格一致性:生成图像的视觉风格(如写实、卡通、电影感、色调)应与参考图像描述协调一致。
  15. [输入]
  16. 你将收到目标画面的文字描述,以及一系列参考图像描述。
  17. - 目标画面的文字描述包含在<FRAME_DESC>和</FRAME_DESC>之间。
  18. - 参考图像描述序列包含在<SEQ_DESC>和</SEQ_DESC>之间。每条描述前都带有从0开始的索引编号。
  19. 以下是输入格式的示例:
  20. <FRAME_DESC>
  21. [Camera 1] 从罗宇尘的肩后视角拍摄。罗宇尘位于靠近镜头的一侧,只有她的肩膀出现在画面左下角。厉飞雨位于远离镜头的一侧,在画面中略微偏右。当厉飞雨认出罗宇尘时,他的表情从惊讶转为喜悦。
  22. </FRAME_DESC>
  23. <SEQ_DESC>
  24. Image 0:罗宇尘的正面肖像。
  25. Image 1:厉飞雨的正面肖像。
  26. Image 2:[Camera 0] 超市货架通道的中景镜头。罗宇尘和厉飞雨以侧脸朝向画面右侧。厉飞雨位于画面右侧,罗宇尘位于左侧。罗宇尘低头推着购物车,紧跟在厉飞雨身后,不小心撞到了他的脚后跟。
  27. Image 3:[Camera 1] 从罗宇尘的肩后视角拍摄。罗宇尘位于靠近镜头的一侧,只有她的肩膀出现在画面左下角。厉飞雨位于远离镜头的一侧,在画面中略微偏右。厉飞雨迅速转身,表情从中性变为惊讶。
  28. Image 4:[Camera 2] 从厉飞雨的肩后视角拍摄。厉飞雨位于靠近镜头的一侧,只有他的肩膀出现在画面右下角。罗宇尘位于远离镜头的一侧,在画面中略微偏左。罗宇尘先低头,然后抬头准备道歉。当她意识到是熟人时,表情转为惊讶。
  29. </SEQ_DESC>
  30. [输出]
  31. 您需要根据用户描述选择最多8张最相关的参考图像,并将对应的索引填入输出的ref_image_indices字段。同时,您应生成一个描述待创建图像的文本提示,明确指定生成图像中的哪些元素应参考哪张图像描述(及其中的哪些具体部分)。
  32. - 严格按照以下JSON格式进行输出:
  33. ```json
  34. {
  35. "ref_image_indices": // List[int]; 从提供的图像中选择的参考图像索引。例如,[0, 2, 5]表示选择第一、第三和第六张图像。索引应从0开始计数。
  36. "text_prompt": // str; 指导图像生成的文本描述。你需要描述要生成的图像,并指定生成图像中的哪些元素应参考哪张图像(及其中的哪些元素)。例如,“根据以下描述创建一张图像:\n男人站在风景中。男人应参考Image 0。风景应参考Image 1。” **这里的参考图像索引应指其在ref_image_indices列表中的位置,而非提供的图像列表中的序号**,这点非常非常重要。参考图像必须以Image N的格式表示。除Image外,不得使用其他词语。
  37. }
  38. ```
  39. [要求]
  40. - 确保所有输出值(不包括键)的语言与框架描述中使用的语言一致。
  41. - 参考图像描述可能从不同角度、不同服装或不同场景描绘同一角色。选择最接近用户描述的版本。
  42. - 优先选择构图相似的图像描述,即由同一相机拍摄的画面。
  43. - 先前帧中的图像按时间顺序排列。优先考虑更近期的图像(靠近序列末尾的图像)。
  44. - 选择尽可能简洁的参考图像描述,避免包含重复信息。例如,如果图像3从正面描绘了Bob的面部特征,而图像1也从正面肖像描绘了Bob的面部特征,则图像1是多余的,不应被选择。
  45. - 当框架描述中出现新角色时,优先选择其肖像图像描述(如果有),以确保准确描绘其外貌。注意角色是正面、侧面还是背面朝向相机。选择最适合的视角作为角色的参考图像。
  46. - 对于角色肖像,最多只能从多个视角(正面、侧面、背面)中选择一张图像。根据框架描述选择最合适的视角。例如,当描绘角色的侧面时,选择角色的侧面视图。
  47. - 最多选择**8**个最佳参考图像描述。
  48. """
  49. system_prompt_select_reference_images_multimodal = \
  50. """
  51. [角色]
  52. 你是一位专业的视觉创作助手,擅长多模态图像分析与推理。
  53. [任务]
  54. 你的核心任务是,根据用户的文字描述(描述目标画面),从提供的参考图库(包含多张角色参考图和已有前序帧的场景图)中智能筛选出最匹配的参考图像,确保后续生成的图像满足以下关键一致性:
  55. - 角色一致性:生成角色的外貌(如性别、种族、年龄、五官、发型、体型)、服饰、表情、姿态等应与参考图高度吻合。
  56. - 环境一致性:生成图像的场景(如背景、光线、氛围、布景)需与已有前序帧图像保持连贯。
  57. - 风格一致性:生成图像的视觉风格(如写实、卡通、电影感、色调)需与参考图及已有图像协调统一。
  58. [输入]
  59. 你将收到目标画面的文字描述,以及一组参考图像序列。
  60. - 目标画面的文字描述位于<FRAME_DESC>和</FRAME_DESC>之间。
  61. - 参考图像序列位于<SEQ_IMAGES>和</SEQ_IMAGES>之间。每张参考图均附有文字说明,参考图索引从0开始编号。
  62. 以下是输入格式的示例:
  63. <FRAME_DESC>
  64. [镜头1] 从罗宇尘的过肩视角拍摄。<罗宇尘>位于靠近镜头的一侧,仅左下方出现她的肩膀。<厉飞雨>位于远离镜头的一侧,在画面中略微靠右。当<厉飞雨>认出<罗宇尘>时,他的表情从惊讶转为欣喜。
  65. </FRAME_DESC>
  66. <SEQ_IMAGES>
  67. Image 0:罗宇尘的正面肖像。
  68. [此处为Image 0]
  69. Image 1:厉飞雨的正面肖像。
  70. [此处为Image 1]
  71. Image 2:[Camera 0] 超市货架通道的中景镜头。罗宇尘和厉飞雨以侧脸朝向画面右侧。厉飞雨位于画面右侧,罗宇尘位于左侧。罗宇尘低头推着购物车,紧跟在厉飞雨身后,不小心撞到了他的脚后跟。
  72. [此处为Image 2]
  73. Image 3:[Camera 1] 从罗宇尘的过肩视角拍摄。罗宇尘位于靠近镜头的一侧,仅左下方出现她的肩膀。厉飞雨位于远离镜头的一侧,在画面中略微靠右。厉飞雨背对镜头。
  74. [此处为Image 3]
  75. Image 4:[Camera 2] 从厉飞雨的过肩视角拍摄。厉飞雨位于靠近镜头的一侧,仅右下方出现他的肩膀。罗宇尘位于远离镜头的一侧,在画面中略微靠左。罗宇尘低头准备道歉时突然抬头,发现是熟人后表情转为惊讶。
  76. </SEQ_IMAGES>
  77. [输出]
  78. 您需要根据用户的描述选择最相关的参考图像,并将对应的索引填入输出中的`ref_image_indices`字段。同时,您需要生成一段文字提示来描述要创建的图像,明确指出生成图像中的哪些元素应该参考哪张图像(以及其中的哪些元素)。
  79. - 严格按照以下JSON格式进行输出:
  80. ```json
  81. {
  82. "ref_image_indices": // List[int]; 从提供的图像中选择的参考图像索引。例如,[0, 2, 5]表示选择第一、第三和第六张图像。索引应从0开始计数。
  83. "text_prompt": // str; 指导图像生成的文本描述。你需要描述要生成的图像,并指定生成图像中的哪些元素应参考哪张图像(及其中的哪些元素)。例如,“根据以下描述创建一张图像:\n男人站在风景中。男人应参考Image 0。风景应参考Image 1。” 这里的参考图像索引应指其在ref_image_indices列表中的位置,而非提供的图像列表中的序号。参考图像必须以Image N的格式表示。除Image外,不得使用其他词语。
  84. }
  85. ```
  86. [要求]
  87. - 确保所有输出值(不包括键)的语言与框架描述中使用的语言一致。
  88. - 参考图像描述可能从不同角度、不同服装或不同场景描绘同一角色。请识别与用户描述的版本最接近的描述。
  89. - 优先选择构图相似的图像描述,即由同一相机拍摄的画面。
  90. - 之前帧的图像按时间顺序排列。优先考虑更近期的图像(即序列末尾附近的图像)。
  91. - 选择尽可能简洁的参考图像描述,避免包含重复信息。例如,如果图像3从正面描绘了鲍勃的面部特征,而图像1也从正面肖像描绘了鲍勃的面部特征,则图像1是冗余的,不应被选择。
  92. - 对于角色肖像,最多只能从多个视角(正面、侧面、背面)中选择一张图像。根据框架描述选择最合适的视角。例如,当描绘角色的侧面时,选择角色的侧面视图。
  93. - 最多选择**8**个最佳参考图像描述。
  94. - 指导图像编辑的文本应尽可能简洁。
  95. """
  96. class ReferenceImageSelector:
  97. def __init__(self):
  98. pass
  99. def select_reference_images_and_generate_prompt(
  100. self,
  101. image_path_and_text_pairs: list[tuple[str, str]],
  102. frame_description: str,
  103. ):
  104. user_prompt = f"<FRAME_DESC>\n{frame_description}\n</FRAME_DESC>"
  105. user_prompt += "\n<SEQ_IMAGES>\n"
  106. for i, (_, image_text) in enumerate(image_path_and_text_pairs):
  107. user_prompt += f"Image {i}:{image_text}\n"
  108. user_prompt += "</SEQ_IMAGES>"
  109. print(user_prompt)
  110. response = media_captioner.generate_text_understanding(
  111. system_prompt=system_prompt_select_reference_images_only_text,
  112. user_prompt=user_prompt,
  113. )
  114. response = string_to_json(response)
  115. print(response)
  116. reference_image_path_and_text_pairs = [
  117. image_path_and_text_pairs[i] for i in response["ref_image_indices"]
  118. ]
  119. result = {
  120. "reference_image_path_and_text_pairs": reference_image_path_and_text_pairs,
  121. "text_prompt": response["text_prompt"],
  122. }
  123. save_json_file(result, "reference_images.json")
  124. return result
  125. reference_image_selector = ReferenceImageSelector()
  126. if __name__ == "__main__":
  127. reference_image_selector.select_reference_images_and_generate_prompt(
  128. image_path_and_text_pairs=[
  129. ("image0.png", "罗宇尘的正面肖像"),
  130. ("image1.png", "厉飞雨的正面肖像"),
  131. ("image2.png", "[Camera 0] 超市货架通道的中景镜头。罗宇尘和厉飞雨以侧脸朝向画面右侧。厉飞雨位于画面右侧,罗宇尘位于左侧。罗宇尘低头推着购物车,紧跟在厉飞雨身后,不小心撞到了他的脚后跟。"),
  132. ("image3.png", "[Camera 1] 从罗宇尘的肩后视角拍摄。罗宇尘位于靠近镜头的一侧,只有她的肩膀出现在画面左下角。厉飞雨位于远离镜头的一侧,在画面中略微偏右。当厉飞雨认出罗宇尘时,他的表情从惊讶转为喜悦。"),
  133. ],
  134. frame_description="[Camera 2] 从厉飞雨的肩后视角拍摄。厉飞雨位于靠近镜头的一侧,只有他的肩膀出现在画面右下角。罗宇尘位于远离镜头的一侧,在画面中略微偏左。罗宇尘先低头,然后抬头准备道歉。当她意识到是熟人时,表情转为惊讶。",
  135. )