Instructions to use Cccccz/HY with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Diffusers
How to use Cccccz/HY with Diffusers:
pip install -U diffusers transformers accelerate
import torch from diffusers import DiffusionPipeline # switch to "mps" for apple devices pipe = DiffusionPipeline.from_pretrained("Cccccz/HY", dtype=torch.bfloat16, device_map="cuda") prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k" image = pipe(prompt).images[0] - Notebooks
- Google Colab
- Kaggle
File size: 12,721 Bytes
74da989 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 | from typing import List
import numpy as np
import torch
import math
from einops import rearrange
from scipy.spatial.transform import Rotation as R_scipy
from hyvideo.utils.retrieval_context import calculate_fov_overlap_similarity
from typing import List, Dict, Tuple
from distributed.parallel_state import get_sp_parallel_rank, get_sp_world_size
def shard_latents_dim_across_sp(latents: torch.Tensor, total_dim) -> torch.Tensor:
sp_world_size = get_sp_world_size()
rank_in_sp_group = get_sp_parallel_rank()
# latents = latents[:, :, :num_latent_t]
if sp_world_size > 1:
if total_dim == 5:
latents = rearrange(
latents, "b c (n s) h w -> b c n s h w", n=sp_world_size
).contiguous()
latents = latents[:, :, rank_in_sp_group, :, :, :]
elif total_dim == 4:
latents = rearrange(
latents, "b (n s) h w -> b n s h w", n=sp_world_size
).contiguous()
latents = latents[:, rank_in_sp_group, :, :, :]
elif total_dim == 3:
latents = rearrange(
latents, "b (n s) c -> b n s c", n=sp_world_size
).contiguous()
latents = latents[:, rank_in_sp_group, :, :]
elif total_dim == 2:
latents = rearrange(
latents, "b (n s)-> b n s", n=sp_world_size
).contiguous()
latents = latents[:, rank_in_sp_group, :]
elif total_dim == 1:
latents = rearrange(latents, "(n s)-> n s", n=sp_world_size).contiguous()
latents = latents[rank_in_sp_group, :]
else:
raise NotImplementedError(f"total_dim {total_dim} not supported")
return latents
def select_mem_frames_wan(
w2c_list: List[np.ndarray],
current_frame_idx: int,
memory_frames: int,
temporal_context_size: int,
pred_latent_size: int,
pos_weight: float = 1.0,
ang_weight: float = 1.0,
device=None,
points_local=None,
) -> List[int]:
"""
为给定帧选择记忆帧和上下文帧,基于复杂的四帧片段距离计算。
参数:
w2c_list (List[np.ndarray]): 包含所有N个4x4外参矩阵的列表。
current_frame_idx (int): 当前要处理的帧的索引。
memory_frames (int): 需要选择的记忆帧总数。
context_size (int): 需要选择的上下文帧总数。
pos_weight (float): 空间距离的权重。
ang_weight (float): 角度距离的权重。
返回:
List[int]: 包含选定记忆帧和上下文帧索引的列表。
"""
num_total_frames = len(w2c_list)
# 检查当前帧是否能构成一个完整的4帧片段
if current_frame_idx >= num_total_frames or current_frame_idx < 3:
raise ValueError("当前帧索引必须在 w2c_list 的有效范围内,且至少为3。")
# 1. 选择上下文帧 (Context Frames)
start_context_idx = max(0, current_frame_idx - temporal_context_size)
context_frames_indices = list(range(start_context_idx, current_frame_idx))
# 2. 计算记忆帧 (Memory Frames) 的候选池
candidate_distances = []
query_clip_indices = list(
range(
current_frame_idx,
(
current_frame_idx + pred_latent_size
if current_frame_idx + pred_latent_size <= num_total_frames
else num_total_frames
),
)
)
historical_clip_indices = list(
range(0, current_frame_idx - temporal_context_size, 4)
)
memory_frames_indices = [] # add the first latent frame as context
memory_frames = memory_frames - temporal_context_size
for hist_idx in historical_clip_indices:
total_dist = 0
hist_w2c_1 = w2c_list[hist_idx]
hist_w2c_2 = w2c_list[hist_idx + 2]
for query_idx in query_clip_indices:
dist_1_for_query_idx = 1.0 - calculate_fov_overlap_similarity(
w2c_list[query_idx],
hist_w2c_1,
fov_h_deg=60.0,
fov_v_deg=35.0,
device=device,
points_local=points_local,
)
dist_2_for_query_idx = 1.0 - calculate_fov_overlap_similarity(
w2c_list[query_idx],
hist_w2c_2,
fov_h_deg=60.0,
fov_v_deg=35.0,
device=device,
points_local=points_local,
)
dist_for_query_idx = (dist_1_for_query_idx + dist_2_for_query_idx) / 2.0
total_dist += dist_for_query_idx
final_clip_distance = total_dist / len(query_clip_indices)
candidate_distances.append((hist_idx, final_clip_distance))
candidate_distances.sort(key=lambda x: x[1])
# 遍历排序后的候选片段,直到收集到足够的记忆帧
for start_idx, _ in candidate_distances:
if start_idx not in memory_frames_indices:
memory_frames_indices.extend(range(start_idx, start_idx + 4))
# 检查是否已达到 memory_size 的要求
if len(memory_frames_indices) >= memory_frames:
break
# 4. 组合并去重,以确保没有重复的帧
selected_frames_set = set(context_frames_indices)
selected_frames_set.update(memory_frames_indices)
final_selected_frames = sorted(list(selected_frames_set))
assert len(final_selected_frames) == memory_frames + temporal_context_size
return final_selected_frames
# --- 核心函数重构 ---
# def select_memory_frames(w2c_list: List[np.ndarray], current_frame_idx: int, memory_size: int,
# context_size: int, pos_weight: float = 1.0, ang_weight: float = 1.0) -> List[int]:
# """
# 为给定帧选择记忆帧和上下文帧,基于复杂的四帧片段距离计算。
# 参数:
# w2c_list (List[np.ndarray]): 包含所有N个4x4外参矩阵的列表。
# current_frame_idx (int): 当前要处理的帧的索引。
# memory_size (int): 需要选择的记忆帧总数。
# context_size (int): 需要选择的上下文帧总数。
# pos_weight (float): 空间距离的权重。
# ang_weight (float): 角度距离的权重。
# 返回:
# List[int]: 包含选定记忆帧和上下文帧索引的列表。
# """
# num_total_frames = len(w2c_list)
# # 检查当前帧是否能构成一个完整的4帧片段
# if current_frame_idx >= num_total_frames or current_frame_idx < 3:
# raise ValueError("当前帧索引必须在 w2c_list 的有效范围内,且至少为3。")
# # 1. 选择上下文帧 (Context Frames)
# start_context_idx = max(0, current_frame_idx - context_size)
# context_frames_indices = list(range(start_context_idx, current_frame_idx))
# # 2. 计算记忆帧 (Memory Frames) 的候选池
# candidate_distances = []
# query_clip_indices = list(range(current_frame_idx, current_frame_idx + 4))
# # 遍历所有历史片段,将每个片段作为记忆帧候选
# # 历史片段的起始索引必须是 4 的倍数,且不能与上下文帧重叠
# for i in range(0, current_frame_idx, 4):
# historical_clip_indices = list(range(i, i + 4))
# # 排除上下文帧,如果历史片段与上下文帧有任何交集,就跳过
# is_context_clip = any(idx in context_frames_indices for idx in historical_clip_indices)
# if is_context_clip:
# continue
# avg_distance = calculate_complex_clip_distance(w2c_list, query_clip_indices, historical_clip_indices,
# pos_weight, ang_weight)
# # 存储 (片段起始帧索引, 平均距离)
# candidate_distances.append((i, avg_distance))
# # 按平均距离从小到大排序
# candidate_distances.sort(key=lambda x: x[1])
# # 3. 选取最相似的 `memory_size` 个帧
# memory_frames_indices = []
# # 遍历排序后的候选片段,直到收集到足够的记忆帧
# for start_idx, _ in candidate_distances:
# # 将整个片段的帧都添加到记忆帧列表中
# memory_frames_indices.extend(range(start_idx, start_idx + 4))
# # 检查是否已达到 memory_size 的要求
# if len(memory_frames_indices) >= memory_size:
# break
# # 4. 组合并去重,以确保没有重复的帧
# selected_frames_set = set(context_frames_indices)
# selected_frames_set.update(memory_frames_indices)
# final_selected_frames = sorted(list(selected_frames_set))
# return final_selected_frames
def calculate_complex_clip_distance(
w2c_list: List[np.ndarray],
query_clip_indices: List[int],
historical_clip_indices: List[int],
pos_weight: float = 1.0,
ang_weight: float = 1.0,
) -> float:
"""
计算查询片段与历史片段之间的复杂姿态距离。
该距离是基于查询片段的第二帧和第四帧与历史片段的每一帧的平均距离。
"""
if len(query_clip_indices) < 4 or len(historical_clip_indices) < 4:
raise ValueError("片段索引列表必须包含4个元素。")
# 提取查询片段的第二帧和第四帧的w2c矩阵
query_2nd_w2c = w2c_list[query_clip_indices[1]] # 第二帧
query_4th_w2c = w2c_list[query_clip_indices[3]] # 第四帧
# 1. 计算查询片段第二帧与历史片段每帧的平均距离
dists_from_2nd = []
for hist_idx in historical_clip_indices:
hist_w2c = w2c_list[hist_idx]
dist = calculate_pose_distance_from_w2c(
query_2nd_w2c, hist_w2c, pos_weight, ang_weight
)
dists_from_2nd.append(dist)
avg_dist_from_2nd = np.mean(dists_from_2nd)
# 2. 计算查询片段第四帧与历史片段每帧的平均距离
dists_from_4th = []
for hist_idx in historical_clip_indices:
hist_w2c = w2c_list[hist_idx]
dist = calculate_pose_distance_from_w2c(
query_4th_w2c, hist_w2c, pos_weight, ang_weight
)
dists_from_4th.append(dist)
avg_dist_from_4th = np.mean(dists_from_4th)
# 3. 将两个平均值再次取平均,得到最终的片段距离
final_clip_distance = (avg_dist_from_2nd + avg_dist_from_4th) / 2.0
return final_clip_distance
def calculate_pose_distance_from_w2c(
w2c_1: np.ndarray,
w2c_2: np.ndarray,
pos_weight: float = 1.0,
ang_weight: float = 1.0,
) -> float:
"""
根据两个 4x4 W2C (World-to-Camera) 矩阵计算它们之间的综合姿态距离。
该距离量化了两个相机姿态的相似度,类似其 FOV 的重叠程度。
参数:
w2c_1 (np.ndarray): 第一个相机的 4x4 World-to-Camera 矩阵。
w2c_2 (np.ndarray): 第二个相机的 4x4 World-to-Camera 矩阵。
pos_weight (float): 空间距离的权重。
ang_weight (float): 角度距离的权重。
返回:
float: 两个姿态之间的综合距离。
"""
def w2c_to_6d_pose(w2c_matrix: np.ndarray) -> np.ndarray:
"""
将 4x4 World-to-Camera (W2C) 矩阵转换为 6D 姿态。
6D 姿态元组为 (x, y, z, pitch, yaw, roll)。
"""
# 提取旋转矩阵 R 和平移向量 t
R_cw = w2c_matrix[:3, :3]
t_cw = w2c_matrix[:3, 3]
# 计算相机在世界坐标系下的位置 C_world
# C_world = -R_cw.T @ t_cw
C_world = -np.dot(R_cw.T, t_cw)
# 将旋转矩阵转换为欧拉角 (pitch, yaw, roll)
# 注意: scipy 默认的欧拉角顺序是 ZYX,对应 yaw, pitch, roll
# 为了与常见的 (pitch, yaw, roll) 顺序匹配,我们手动转换
r = R_scipy.from_matrix(R_cw)
pitch, yaw, roll = r.as_euler("yxz", degrees=True)
return np.array([C_world[0], C_world[1], C_world[2], pitch, yaw, roll])
# 1. 将两个 W2C 矩阵转换为 6D 姿态
pose1_6d = w2c_to_6d_pose(w2c_1)
pose2_6d = w2c_to_6d_pose(w2c_2)
# 2. 计算空间距离 (欧几里得距离)
pos1 = pose1_6d[:3]
pos2 = pose2_6d[:3]
spatial_distance = np.linalg.norm(pos1 - pos2)
# 3. 计算角度距离 (考虑圆周特性)
angles1 = pose1_6d[3:]
angles2 = pose2_6d[3:]
angle_diff = np.abs(angles1 - angles2)
# 修正角度差,确保是最小的圆周距离
angular_distance_vector = np.minimum(angle_diff, 360 - angle_diff)
# 使用欧几里得范数作为综合角度距离
angular_distance = np.linalg.norm(angular_distance_vector)
# 4. 结合两种距离得到综合姿态距离
total_distance = pos_weight * spatial_distance + ang_weight * angular_distance
return total_distance
|