Weight Balls

Given a set of N balls and one of which is defective (weighs less than others), you are allowed to weigh with a balance 3 times to find the defective. Which of the following are possible N?

------------------------------------------------------------------

答案:ABCD

A. 12               B. 16                     C. 20                        D. 24         

 

梅氏砝码问题,<=27的都能称出来

----------------------------------------------------------------------------------------------------------------------------

 

梅氏砝码问题

有4个砝码,共重40克,现有一个天平,问这4个砝码分别为多少克?可以称出1-40克的重量。

----------------------------------------------------------------------------------------------------------------------------

 

这个在数学上叫做梅氏砝码问题,其叙述如下: 
若有n个砝码,重量分别为M1,M2,……,Mn,且能称出从1到(M1+M2+……+Mn)的所有重量,则再加一个砝码,重量为Mn+1=(M1+M2+……+Mn)*2+1,则这n+1个砝码能称出从1到 
(M1+M2+……+Mn+Mn+1)的所有重量。 

取n=1,M1=1,则可以依此类推出所有砝码的重量为: 
1,3,9,27,81,243,……
import numpy as np import matplotlib.pyplot as plt import networkx as nx from matplotlib.patches import Circle from scipy.spatial.distance import cdist from scipy.sparse import lil_matrix try: from sklearn.cluster import KMeans has_sklearn = True except ImportError: print("警告: scikit-learn 未安装,将使用简化的粒球生成方法") has_sklearn = False class GranularBallGraph: def __init__(self, points, n_clusters=10, overlap_threshold=0.1): self.points = points self.n_clusters = n_clusters self.overlap_threshold = overlap_threshold self.balls = [] self.graph = None def generate_granular_balls(self): """生成粒球 - 支持两种方式""" if has_sklearn and len(self.points) > self.n_clusters: # 使用K-Means聚类方法 kmeans = KMeans(n_clusters=self.n_clusters, random_state=0, n_init=10) labels = kmeans.fit_predict(self.points) self.balls = [] for i in range(self.n_clusters): cluster_points = self.points[labels == i] if len(cluster_points) > 0: center = kmeans.cluster_centers_[i] radius = np.max(np.linalg.norm(cluster_points - center, axis=1)) self.balls.append((center, radius, cluster_points)) else: # 简化的粒球生成方法(不使用sklearn) print(f"使用简化的粒球生成方法(点数量: {len(self.points)})") self.balls = [] n = min(self.n_clusters, len(self.points)) indices = np.random.choice(len(self.points), n, replace=False) for idx in indices: center = self.points[idx] # 计算到最近点的距离作为半径 dists = np.linalg.norm(self.points - center, axis=1) dists.sort() radius = dists[min(5, len(dists) - 1)] # 取第5近的距离作为半径 self.balls.append((center, radius, self.points[dists <= radius])) def build_graph(self): """构建粒球图结构""" if not self.balls: print("错误: 未生成粒球,请先调用 generate_granular_balls()") return n_balls = len(self.balls) adj_matrix = lil_matrix((n_balls, n_balls), dtype=int) centers = np.array([ball[0] for ball in self.balls]) radii = np.array([ball[1] for ball in self.balls]) # 计算粒球中心间的距离 dist_matrix = cdist(centers, centers) # 判断粒球是否相交 for i in range(n_balls): for j in range(i + 1, n_balls): # 计算重叠比例 distance = dist_matrix[i, j] min_radius = min(radii[i], radii[j]) if min_radius > 0: # 防止除以零 overlap_ratio = (radii[i] + radii[j] - distance) / min_radius if overlap_ratio > self.overlap_threshold: adj_matrix[i, j] = 1 adj_matrix[j, i] = 1 # 创建NetworkX图 self.graph = nx.Graph() for i in range(n_balls): self.graph.add_node(i, center=centers[i], radius=radii[i]) for i in range(n_balls): for j in adj_matrix.rows[i]: if i < j: # 避免重复添加边 self.graph.add_edge(i, j) def visualize_2d(self, show_points=True, show_balls=True, show_graph=True): """可视化2D粒球图""" if self.points.shape[1] != 2: print("警告: 可视化仅支持2D数据") return plt.figure(figsize=(10, 8)) # 绘制原始点云 if show_points: plt.scatter(self.points[:, 0], self.points[:, 1], c='blue', s=10, alpha=0.6, label='点云') # 绘制粒球 if show_balls and self.balls: for i, (center, radius, _) in enumerate(self.balls): circle = Circle(center, radius, fill=False, edgecolor='red', alpha=0.4, linestyle='--') plt.gca().add_patch(circle) plt.text(center[0], center[1], f'B{i}', fontsize=9, ha='center', va='center') # 绘制图结构 if show_graph and self.graph: pos = {i: ball[0] for i, ball in enumerate(self.balls)} nx.draw(self.graph, pos, node_size=50, node_color='green', edge_color='gray', width=1.5, alpha=0.7) plt.title('粒球图 (Granular Ball Graph)') plt.xlabel('X') plt.ylabel('Y') plt.grid(alpha=0.3) plt.legend() plt.axis('equal') plt.show() def reconstruct_surface(self, resolution=0.1): """简单的表面重建(仅用于2D数据)""" if self.points.shape[1] != 2: print("警告: 表面重建目前仅支持2D数据") return if not self.balls: print("错误: 未生成粒球,请先调用 generate_granular_balls()") return # 创建网格 x_min, y_min = np.min(self.points, axis=0) x_max, y_max = np.max(self.points, axis=0) x = np.arange(x_min, x_max, resolution) y = np.arange(y_min, y_max, resolution) xx, yy = np.meshgrid(x, y) grid_points = np.c_[xx.ravel(), yy.ravel()] # 判断点是否在任意粒球内 surface_mask = np.zeros(len(grid_points), dtype=bool) for center, radius, _ in self.balls: dist = np.linalg.norm(grid_points - center, axis=1) surface_mask |= (dist <= radius) # 可视化重建表面 plt.figure(figsize=(10, 8)) plt.scatter(grid_points[surface_mask, 0], grid_points[surface_mask, 1], c='blue', s=1, alpha=0.3, label='重建表面') plt.scatter(self.points[:, 0], self.points[:, 1], c='red', s=15, alpha=0.7, label='原始点') # 添加粒球中心 centers = np.array([ball[0] for ball in self.balls]) plt.scatter(centers[:, 0], centers[:, 1], c='green', s=50, marker='x', label='粒球中心') plt.title('基于粒球图的表面重建') plt.xlabel('X') plt.ylabel('Y') plt.legend() plt.grid(alpha=0.3) plt.axis('equal') plt.show() # 示例用法 if __name__ == "__main__": # 生成示例点云数据(2D圆环) np.random.seed(42) n_points = 700 theta = np.linspace(0, 2 * np.pi, n_points) r = 5 + np.random.rand(n_points) * 2 points = np.c_[r * np.cos(theta), r * np.sin(theta)] noise = np.random.randn(n_points, 2) * 0.3 points += noise # 创建并构建粒球图 print("创建粒球图...") gbg = GranularBallGraph(points, n_clusters=10) gbg.generate_granular_balls() gbg.build_graph() # 输出信息 if gbg.balls: print(f"生成粒球数量: {len(gbg.balls)}") avg_radius = np.mean([ball[1] for ball in gbg.balls]) print(f"平均半径: {avg_radius:.2f}") if gbg.graph: print(f"图结构: {gbg.graph.number_of_nodes()} 个节点, {gbg.graph.number_of_edges()} 条边") # 可视化 gbg.visualize_2d(show_points=True, show_balls=True, show_graph=True) gbg.reconstruct_surface()
07-22
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>双色球模拟开奖系统</title> <style> /* 核心样式 */ .container { text-align: center; margin: 20px auto; max-width: 800px; font-family: Arial, sans-serif; } .balls-container { margin: 20px; min-height: 60px; } .ball { display: inline-block; width: 40px; height: 40px; line-height: 40px; border-radius: 50%; margin: 5px; font-weight: bold; opacity: 0; transform: scale(0.5); transition: all 0.5s ease-out; } .ball.show { opacity: 1; transform: scale(1); } .red-ball { background: #ff4444; color: white; } .blue-ball { background: #4444ff; color: white; } #startBtn { padding: 12px 24px; font-size: 18px; background: #4CAF50; color: white; border: none; border-radius: 5px; cursor: pointer; transition: background 0.3s; } #startBtn:hover { background: #45a049; } #startBtn:disabled { background: #cccccc; cursor: not-allowed; } </style> </head> <body> <div class="container"> <h2>🎱 双色球模拟开奖系统</h2> <button id="startBtn" onclick="startLottery()">开始摇号</button> <div class="result-area"> <div id="redBalls" class="balls-container"></div> <div id="blueBall" class="balls-container"></div> </div> </div> <script> // 红球生成算法(无重复) function generateRedBalls() { const balls = new Set() while(balls.size < 6) { balls.add(Math.floor(Math.random() * 33) + 1) } return [...balls].sort((a,b) => a - b) } // 蓝球生成算法 function generateBlueBall() { return Math.floor(Math.random() * 16) + 1 } // 动画显示逻辑 function startLottery() { const btn = document.getElementById('startBtn') btn.disabled = true btn.textContent = '摇号中...' // 清空上次结果 document.getElementById('redBalls').innerHTML = '' document.getElementById('blueBall').innerHTML = '' // 生成新号码 const reds = generateRedBalls() const blue = generateBlueBall() // 红球逐个显示 reds.forEach((num, index) => { setTimeout(() => { const ball = document.createElement('div') ball.className = 'ball red-ball' ball.textContent = num.toString().padStart(2, '0') document.getElementById('redBalls').appendChild(ball) // 触发动画 setTimeout(() => ball.classList.add('show'), 10) }, 500 * index) }) // 蓝球延迟显示 setTimeout(() => { const ball = document.createElement('div') ball.className = 'ball blue-ball' ball.textContent = blue.toString().padStart(2, '0') document.getElementById('blueBall').appendChild(ball) setTimeout(() => { ball.classList.add('show') btn.disabled = false btn.textContent = '重新摇号' }, 10) }, 500 * reds.length + 1000) } </script> </body> </html> 以上面的代码为基础,增加以下功能:机选任意注并打出这些号码组合
03-19
import numpy as np import cv2 from scipy.spatial import KDTree from scipy.optimize import least_squares from sklearn.decomposition import PCA from sklearn.cluster import KMeans from sklearn.neighbors import NearestNeighbors import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import os import time class GranularBallSFM: def __init__(self, params=None): # 算法参数(基于论文中的理论推导和实验验证) self.params = params or { # 特征预处理参数 'sift_contrast_threshold': 0.04, 'superpoint_threshold': 0.005, 'entropy_window_size': 15, # 粒度球生成参数 'init_radius': 100, 'min_radius': 15, 'max_radius': 50, 'eta': 0.8, # 梯度-半径转换系数 'kappa': 20, # 熵项缩放系数 'tau': 5, # 熵项温度参数 'topology_tau': 5, # 拓扑容差参数 # 粗粒度重建参数 'coarse_threshold': 50, 'subblock_size': 8, # 细粒度重建参数 'fine_threshold': 15, 'huber_delta': 2.0, # 低纹理补足参数 'textureless_entropy': 2.0, 'textureless_radius': 100, 'icp_lambda': 0.1, # 可视化参数 'visualize': True } # 存储中间结果 self.images = [] self.keypoints = [] self.descriptors = [] self.entropy_maps = [] self.gradient_maps = [] self.granular_balls = [] self.topology_graph = None self.camera_poses = [] self.point_cloud = [] self.reconstructed_mesh = None def load_images(self, image_paths): """加载图像序列""" print(f"加载 {len(image_paths)} 张图像...") self.images = [cv2.imread(path) for path in image_paths] self.images = [cv2.cvtColor(img, cv2.COLOR_BGR2RGB) for img in self.images] self.images = [cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) for img in self.images] return self.images def feature_preprocessing(self): """特征预处理(4.1节)""" print("执行特征预处理...") sift = cv2.SIFT_create(contrastThreshold=self.params['sift_contrast_threshold']) self.keypoints = [] self.descriptors = [] self.entropy_maps = [] self.gradient_maps = [] for img in self.images: # 1. 计算SIFT特征 kp, des = sift.detectAndCompute(img, None) # 2. 计算局部熵图 entropy_map = self._compute_entropy_map(img) # 3. 计算梯度幅值图 gradient_map = self._compute_gradient_map(img) self.keypoints.append(kp) self.descriptors.append(des) self.entropy_maps.append(entropy_map) self.gradient_maps.append(gradient_map) return self.keypoints, self.descriptors, self.entropy_maps, self.gradient_maps def _compute_entropy_map(self, img): """计算局部熵图(公式4)""" h, w = img.shape entropy_map = np.zeros((h, w)) win_size = self.params['entropy_window_size'] half_win = win_size // 2 for y in range(half_win, h - half_win): for x in range(half_win, w - half_win): window = img[y - half_win:y + half_win + 1, x - half_win:x + half_win + 1] hist = np.histogram(window, bins=256, range=(0, 255))[0] hist = hist / hist.sum() + 1e-10 # 避免除以零 entropy = -np.sum(hist * np.log2(hist)) entropy_map[y, x] = entropy # 归一化 entropy_map = (entropy_map - entropy_map.min()) / (entropy_map.max() - entropy_map.min()) return entropy_map def _compute_gradient_map(self, img): """计算梯度幅值图(公式3)""" sobel_x = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) sobel_y = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3) gradient_magnitude = np.sqrt(sobel_x ** 2 + sobel_y ** 2) # 归一化 gradient_magnitude = (gradient_magnitude - gradient_magnitude.min()) / \ (gradient_magnitude.max() - gradient_magnitude.min()) return gradient_magnitude def generate_granular_balls(self, img_idx=0): """粒度球生成算法(4.2节)""" print(f"为图像 {img_idx} 生成粒度球...") img = self.images[img_idx] entropy_map = self.entropy_maps[img_idx] gradient_map = self.gradient_maps[img_idx] kps = self.keypoints[img_idx] h, w = img.shape init_radius = self.params['init_radius'] min_radius = self.params['min_radius'] max_radius = self.params['max_radius'] eta = self.params['eta'] kappa = self.params['kappa'] tau = self.params['tau'] # 初始化粗粒度粒球 balls = [] queue = [] # 创建初始网格覆盖 for y in range(init_radius // 2, h, init_radius): for x in range(init_radius // 2, w, init_radius): center = (x, y) radius = init_radius projection = self._get_projection_area(img, center, radius) ball = {'center': center, 'radius': radius, 'projection': projection} queue.append(ball) # 自适应粒度分裂 balls_fine = [] while queue: ball = queue.pop(0) center = ball['center'] radius = ball['radius'] projection = ball['projection'] # 计算平均梯度(公式3) G_avg = np.mean([gradient_map[p[1], p[0]] for p in projection]) # 计算局部熵(公式4) hist = np.histogram([img[p[1], p[0]] for p in projection], bins=256, range=(0, 255))[0] hist = hist / hist.sum() + 1e-10 E_local = -np.sum(hist * np.log2(hist)) # 计算自适应半径(公式2) r_k = eta * G_avg + kappa * np.exp(-E_local / tau) # 粒度决策 if r_k < min_radius: # 细粒度区域 - 分裂 sub_balls = self._split_ball(ball, r_k, img) for sub_ball in sub_balls: if sub_ball['radius'] > max_radius: queue.append(sub_ball) else: balls_fine.append(sub_ball) elif r_k > max_radius: # 需要重新分裂 ball['radius'] = r_k queue.append(ball) else: # 最优粒度 - 保留 ball['radius'] = r_k balls.append(ball) balls += balls_fine self.granular_balls = balls # 构建拓扑图(公式8) self.topology_graph = self._build_topology_graph(balls) return balls, self.topology_graph def _get_projection_area(self, img, center, radius): """获取粒球投影区域""" h, w = img.shape xc, yc = center projection = [] for y in range(max(0, int(yc - radius)), min(h, int(yc + radius + 1))): for x in range(max(0, int(xc - radius)), min(w, int(xc + radius + 1))): if (x - xc) ** 2 + (y - yc) ** 2 <= radius ** 2: projection.append((x, y)) return projection def _split_ball(self, ball, target_radius, img): """分裂粒球""" center = ball['center'] radius = ball['radius'] projection = ball['projection'] # 提取粒球内特征点 points = [] for p in projection: points.append(p) if len(points) < 4: # 最少需要4个点进行聚类 return [ball] # K-means聚类 - 修复了括号问题 k = max(2, int(np.sqrt(len(points))) // 2 kmeans = KMeans(n_clusters=k, random_state=0).fit(points) labels = kmeans.labels_ centers = kmeans.cluster_centers_ # 创建子粒球 sub_balls = [] for i in range(k): cluster_points = [points[j] for j in range(len(points)) if labels[j] == i] if not cluster_points: continue # 计算新球心和新半径 center_new = (int(centers[i][0]), int(centers[i][1])) distances = [np.linalg.norm(np.array(p) - np.array(center_new)) for p in cluster_points] radius_new = min(target_radius, np.max(distances) if distances else target_radius) # 确保半径不小于最小值 radius_new = max(radius_new, self.params['min_radius']) projection_new = self._get_projection_area(img, center_new, radius_new) sub_ball = {'center': center_new, 'radius': radius_new, 'projection': projection_new} sub_balls.append(sub_ball) return sub_balls def _build_topology_graph(self, balls): """构建粒球拓扑图(公式8)""" print("构建拓扑图...") centers = [ball['center'] for ball in balls] radii = [ball['radius'] for ball in balls] tau = self.params['topology_tau'] # 使用KDTree加速邻域搜索 kdtree = KDTree(centers) graph = {i: [] for i in range(len(balls))} for i, ball in enumerate(balls): # 查找邻近粒球 neighbors = kdtree.query_ball_point(ball['center'], ball['radius'] + max(radii) + tau) for j in neighbors: if i == j: continue # 计算中心距离 dist = np.linalg.norm(np.array(ball['center']) - np.array(balls[j]['center'])) # 检查是否相交(公式8) if dist <= ball['radius'] + balls[j]['radius'] + tau: graph[i].append(j) return graph def hierarchical_reconstruction(self): """分层三维重建(4.3节)""" print("开始分层三维重建...") # 阶段1: 粗粒度全局骨架构建 self.coarse_global_reconstruction() # 阶段2: 细粒度局部BA优化 self.fine_grained_ba() # 阶段3: 低纹理区域补足 self.textureless_completion() print("三维重建完成!") return self.point_cloud, self.camera_poses, self.reconstructed_mesh def coarse_global_reconstruction(self): """粗粒度全局骨架构建(4.3.1节)""" print("粗粒度全局骨架构建...") coarse_balls = [ball for ball in self.granular_balls if ball['radius'] > self.params['coarse_threshold']] # 1. 计算EWGD描述子(公式14-16) for ball in coarse_balls: # 获取粒球内的特征点 features = self._get_features_in_ball(ball) if not features: continue # 计算SIFT聚合特征(公式14) sift_features = [f[2] for f in features if f[2] is not None] if sift_features: sift_agg = np.mean(sift_features, axis=0)[:64] # 64维均值向量 else: sift_agg = np.zeros(64) # 计算熵权子块特征(公式15) subblock_feature = self._compute_entropy_weighted_subblocks(ball) # 拼接EWGD描述子(公式16) ewgd = np.concatenate((sift_agg, subblock_feature)) ball['ewgd'] = ewgd # 估计法向量(PCA) points = [f[:2] for f in features] if len(points) >= 3: pca = PCA(n_components=3) pca.fit(points) ball['normal'] = pca.components_[2] # 最小特征值对应的特征向量 else: ball['normal'] = np.array([0, 0, 1]) # 2. 全局旋转优化(公式17) self._global_rotation_optimization(coarse_balls) # 初始化相机位姿 self.camera_poses = [np.eye(4) for _ in range(len(self.images))] # 初始化点云 self.point_cloud = self._initialize_point_cloud(coarse_balls) def _get_features_in_ball(self, ball): """获取粒球内的特征点""" features = [] center = ball['center'] radius = ball['radius'] for i, kp in enumerate(self.keypoints[0]): # 假设使用第一张图像的特征点 x, y = kp.pt if (x - center[0]) ** 2 + (y - center[1]) ** 2 <= radius ** 2: desc = self.descriptors[0][i] if self.descriptors[0] is not None else None features.append((x, y, desc)) return features def _compute_entropy_weighted_subblocks(self, ball): """计算熵权子块特征(公式15)""" center = ball['center'] radius = ball['radius'] img = self.images[0] entropy_map = self.entropy_maps[0] subblock_size = self.params['subblock_size'] # 划分粒球为子块 x_min = max(0, int(center[0] - radius)) x_max = min(img.shape[1], int(center[0] + radius)) y_min = max(0, int(center[1] - radius)) y_max = min(img.shape[0], int(center[1] + radius)) subblock_width = (x_max - x_min) // subblock_size subblock_height = (y_max - y_min) // subblock_size subblock_feature = np.zeros(128) # 简化版本 # 简化实现:实际应使用更复杂的特征提取 for i in range(subblock_size): for j in range(subblock_size): # 计算子块位置 x_start = x_min + i * subblock_width x_end = x_min + (i + 1) * subblock_width y_start = y_min + j * subblock_height y_end = y_min + (j + 1) * subblock_height if x_start >= x_end or y_start >= y_end: continue # 计算子块熵值 sub_entropy = np.mean(entropy_map[y_start:y_end, x_start:x_end]) # 计算权重(熵越高权重越大) weight = np.exp(sub_entropy) # 简化权重计算 # 提取子块特征(简化实现) sub_img = img[y_start:y_end, x_start:x_end] sub_feature = np.histogram(sub_img.flatten(), bins=128, range=(0, 255))[0] sub_feature = sub_feature / sub_feature.sum() if sub_feature.sum() > 0 else sub_feature # 加权累加 subblock_feature += weight * sub_feature return subblock_feature def _global_rotation_optimization(self, coarse_balls): """全局旋转优化(公式17)""" # 简化实现:实际应使用李代数优化 print("执行全局旋转优化...") # 构建法向量图 normals = [ball.get('normal', np.array([0, 0, 1])) for ball in coarse_balls] # 优化目标:最小化相邻粒球法向量差异 # 实际实现应使用更复杂的优化算法 for i, ball in enumerate(coarse_balls): if i not in self.topology_graph: continue neighbors = self.topology_graph[i] if not neighbors: continue # 计算平均法向量 neighbor_normals = [coarse_balls[j].get('normal', np.array([0, 0, 1])) for j in neighbors] avg_normal = np.mean(neighbor_normals, axis=0) avg_normal = avg_normal / np.linalg.norm(avg_normal) # 更新法向量 ball['normal'] = 0.7 * ball['normal'] + 0.3 * avg_normal ball['normal'] = ball['normal'] / np.linalg.norm(ball['normal']) def _initialize_point_cloud(self, coarse_balls): """初始化点云""" point_cloud = [] for ball in coarse_balls: # 简化实现:使用球心作为3D点 # 实际实现应使用三角测量 x, y = ball['center'] z = 0 # 简化假设 normal = ball.get('normal', np.array([0, 0, 1])) point_cloud.append((x, y, z, normal)) return point_cloud def fine_grained_ba(self): """细粒度BA优化(4.3.2节)""" print("细粒度BA优化...") fine_balls = [ball for ball in self.granular_balls if ball['radius'] < self.params['fine_threshold']] # 简化实现:实际应使用LM优化 for ball in fine_balls: # 获取粒球内的3D点 points_in_ball = self._get_points_in_ball(ball) if not points_in_ball: continue # 获取观测到这些点的相机 cameras = self._get_cameras_observing_points(points_in_ball) # 优化残差(公式18) residuals = [] for point_idx in points_in_ball: for cam_idx in cameras: # 计算重投影误差 error = self._compute_reprojection_error(point_idx, cam_idx) # 应用Huber损失(公式19) huber_error = self._huber_loss(error, self.params['huber_delta']) residuals.append(huber_error) # 平均残差(简化) avg_residual = np.mean(residuals) if residuals else 0 # 更新点位置(简化实现) # 实际实现应使用优化算法更新点和相机参数 for point_idx in points_in_ball: self._update_point_position(point_idx, avg_residual) # 更新亏格(公式12-13) self._update_genus() def _get_points_in_ball(self, ball): """获取粒球内的3D点""" points_in_ball = [] center = ball['center'] radius = ball['radius'] for i, point in enumerate(self.point_cloud): x, y, z, _ = point if (x - center[0]) ** 2 + (y - center[1]) ** 2 <= radius ** 2: points_in_ball.append(i) return points_in_ball def _get_cameras_observing_points(self, point_indices): """获取观测到指定点的相机""" # 简化实现:返回所有相机 return list(range(len(self.camera_poses))) def _compute_reprojection_error(self, point_idx, cam_idx): """计算重投影误差""" # 简化实现 return np.random.rand() * 2 # 随机误差 def _huber_loss(self, r, delta): """Huber损失函数(公式19)""" if abs(r) <= delta: return 0.5 * r ** 2 else: return delta * (abs(r) - 0.5 * delta) def _update_point_position(self, point_idx, residual): """更新点位置(简化)""" # 实际实现应使用优化算法 x, y, z, normal = self.point_cloud[point_idx] # 沿法线方向微调 self.point_cloud[point_idx] = (x, y, z + residual * 0.01, normal) def _update_genus(self): """更新亏格(公式12-13)""" # 简化实现 pass def textureless_completion(self): """低纹理区域补足(4.3.3节)""" print("低纹理区域补足...") textureless_balls = [] # 识别低纹理区域(公式21) for ball in self.granular_balls: # 计算局部熵 features = self._get_features_in_ball(ball) if not features: continue intensities = [self.images[0][int(p[1]), int(p[0])] for p in features] hist = np.histogram(intensities, bins=256, range=(0, 255))[0] hist = hist / hist.sum() + 1e-10 E_local = -np.sum(hist * np.log2(hist)) # 检查触发条件 if E_local < self.params['textureless_entropy'] and \ ball['radius'] > self.params['textureless_radius']: textureless_balls.append(ball) # 执行点面ICP(公式22) for ball in textureless_balls: self._point_to_plane_icp(ball) # 孔洞填充 self._fill_holes() def _point_to_plane_icp(self, ball): """点面ICP优化(公式22)""" # 简化实现 center = np.array(ball['center']) normal = ball.get('normal', np.array([0, 0, 1])) # 查找邻近点 points = np.array([p[:3] for p in self.point_cloud]) if len(points) == 0: return nn = NearestNeighbors(n_neighbors=10).fit(points) distances, indices = nn.kneighbors([center]) # 计算参考平面 neighbor_points = points[indices[0]] pca = PCA(n_components=3) pca.fit(neighbor_points) ref_normal = pca.components_[2] ref_point = np.mean(neighbor_points, axis=0) # 更新法向量 ball['normal'] = 0.5 * normal + 0.5 * ref_normal ball['normal'] = ball['normal'] / np.linalg.norm(ball['normal']) def _fill_holes(self): """孔洞填充""" # 简化实现 print("执行孔洞填充...") # 实际实现应使用Poisson表面重建等算法 self.reconstructed_mesh = self.point_cloud def visualize_results(self): """可视化重建结果""" if not self.params['visualize']: return fig = plt.figure(figsize=(15, 10)) # 1. 可视化粒球 ax1 = fig.add_subplot(221) img_idx = 0 img = self.images[img_idx] ax1.imshow(img, cmap='gray') ax1.set_title('Granular Balls') for ball in self.granular_balls: center = ball['center'] radius = ball['radius'] circle = plt.Circle(center, radius, color='r', fill=False, alpha=0.5) ax1.add_patch(circle) # 标记粗粒度球 if ball['radius'] > self.params['coarse_threshold']: ax1.plot(center[0], center[1], 'bo', markersize=3) # 标记细粒度球 elif ball['radius'] < self.params['fine_threshold']: ax1.plot(center[0], center[1], 'go', markersize=3) # 2. 可视化拓扑连接 ax2 = fig.add_subplot(222) ax2.imshow(img, cmap='gray') ax2.set_title('Topology Graph') for i, ball in enumerate(self.granular_balls): if i in self.topology_graph: neighbors = self.topology_graph[i] for j in neighbors: if j > i: # 避免重复绘制 start = ball['center'] end = self.granular_balls[j]['center'] ax2.plot([start[0], end[0]], [start[1], end[1]], 'b-', alpha=0.3) # 3. 可视化点云 if self.point_cloud: ax3 = fig.add_subplot(223, projection='3d') ax3.set_title('3D Point Cloud') points = np.array([p[:3] for p in self.point_cloud]) normals = np.array([p[3] for p in self.point_cloud]) ax3.scatter(points[:, 0], points[:, 1], points[:, 2], c='b', s=1) # 可视化法向量 for i in range(0, len(points), 10): # 每隔10个点显示法向量 start = points[i] end = start + 10 * normals[i] ax3.plot([start[0], end[0]], [start[1], end[1]], [start[2], end[2]], 'r-') # 4. 可视化重建网格(简化) ax4 = fig.add_subplot(224, projection='3d') ax4.set_title('Reconstructed Surface') if self.point_cloud: points = np.array([p[:3] for p in self.point_cloud]) ax4.plot_trisurf(points[:, 0], points[:, 1], points[:, 2], cmap='viridis', alpha=0.8) plt.tight_layout() plt.savefig('granular_ball_sfm_results.png') plt.show() def run_full_pipeline(self, image_paths): """运行完整的三维重建流程""" start_time = time.time() # 1. 加载图像 self.load_images(image_paths) # 2. 特征预处理 self.feature_preprocessing() # 3. 粒度球生成(使用第一张图像) self.generate_granular_balls(img_idx=0) # 4. 分层三维重建 self.hierarchical_reconstruction() # 5. 可视化结果 self.visualize_results() end_time = time.time() print(f"完整流程耗时: {end_time - start_time:.2f}秒") return self.point_cloud, self.camera_poses, self.reconstructed_mesh # 使用示例 if __name__ == "__main__": # 图像路径(替换为您的图像序列) image_dir = "path/to/your/images" image_paths = [os.path.join(image_dir, f) for f in sorted(os.listdir(image_dir)) if f.endswith(('.jpg', '.png', '.jpeg'))] # 创建并运行算法 sfm = GranularBallSFM() point_cloud, camera_poses, reconstructed_mesh = sfm.run_full_pipeline(image_paths[:3]) # 使用前3张图像测试 # 保存结果(根据实际需要扩展) np.save("point_cloud.npy", np.array(point_cloud)) np.save("camera_poses.npy", np.array(camera_poses)) print("三维重建结果已保存!")"D:\Python Charm\Python Pro\pythonProject1\.venv\Scripts\python.exe" C:\Users\英杰\Desktop\777\代码\最终算法\pythonProject1\算法大框架.py File "C:\Users\英杰\Desktop\777\代码\最终算法\pythonProject1\算法大框架.py", line 228 k = max(2, int(np.sqrt(len(points))) // 2 ^ SyntaxError: '(' was never closed 进程已结束,退出代码为 1
08-07
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>双色球数据分析与预测</title> <link rel="stylesheet" href="https://s2.ssl.qhres2.com/static/56662140ef7d5d03.css"> <link rel="stylesheet" href="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-100-M/font-awesome/6.0.0/css/all.min.css"> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <style> :root { --primary-white: #f9f9f9; --primary-green: #8daa92; --primary-dark: #333333; --primary-gray: #666666; --accent-green: #5a8f6a; --shadow-light: rgba(0, 0, 0, 0.05); --shadow-medium: rgba(0, 0, 0, 0.1); --red-ball: #e74c3c; --blue-ball: #3498db; } body { font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif; background-color: var(--primary-white); color: var(--primary-dark); line-height: 1.6; margin: 0; padding: 0; min-height: 100vh; display: flex; flex-direction: column; } .container { max-width: 1200px; margin: 0 auto; padding: 0 2rem; } header { background-color: var(--primary-white); padding: 2rem 0; border-bottom: 1px solid var(--shadow-light); position: relative; overflow: hidden; } .header-content { display: flex; justify-content: space-between; align-items: center; } .logo { font-size: 1.8rem; font-weight: bold; color: var(--accent-green); display: flex; align-items: center; } .logo i { margin-right: 0.5rem; color: var(--primary-green); } nav ul { display: flex; list-style: none; gap: 2rem; } nav a { text-decoration: none; color: var(--primary-gray); font-weight: 500; transition: color 0.3s; position: relative; } nav a:hover { color: var(--accent-green); } nav a::after { content: ""; position: absolute; bottom: -0.5rem; left: 0; width: 0; height: 2px; background-color: var(--accent-green); transition: width 0.3s; } nav a:hover::after { width: 100%; } .hero { text-align: center; padding: 4rem 0; margin-bottom: 3rem; } .hero h1 { font-size: 2.5rem; margin-bottom: 1.5rem; color: var(--primary-dark); font-weight: 600; } .hero p { font-size: 1.2rem; color: var(--primary-gray); max-width: 800px; margin: 0 auto 2rem; } .section-title { font-size: 2rem; margin-bottom: 2rem; color: var(--accent-green); position: relative; display: inline-block; } .section-title::after { content: ""; position: absolute; bottom: -0.5rem; left: 0; width: 60%; height: 2px; background-color: var(--primary-green); } .chart-container { background-color: white; border-radius: 0.5rem; box-shadow: 0 4px 6px var(--shadow-light); padding: 2rem; margin-bottom: 3rem; transition: transform 0.3s, box-shadow 0.3s; } .chart-container:hover { transform: translateY(-5px); box-shadow: 0 10px 15px var(--shadow-medium); } .data-section { padding: 3rem 0; } .data-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 2rem; margin-top: 2rem; } .data-card { background-color: white; border-radius: 0.5rem; box-shadow: 0 4px 6px var(--shadow-light); padding: 1.5rem; transition: all 0.3s ease; } .data-card:hover { transform: translateY(-3px); box-shadow: 0 6px 12px var(--shadow-medium); } .card-title { font-size: 1.25rem; color: var(--accent-green); margin-bottom: 1rem; display: flex; align-items: center; } .card-title i { margin-right: 0.5rem; } .prediction-section { background: linear-gradient(135deg, #f8fff9 0%, #e6f7e9 100%); border-left: 4px solid var(--accent-green); padding: 2rem; margin: 2rem 0; border-radius: 0 0.5rem 0.5rem 0; } .number-balls { display: flex; flex-wrap: wrap; gap: 0.8rem; margin: 1.5rem 0; justify-content: center; } .ball { width: 50px; height: 50px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: bold; font-size: 1.2rem; color: white; box-shadow: 0 4px 6px rgba(0,0,0,0.1); transition: transform 0.3s; } .ball:hover { transform: scale(1.1); } .red-ball { background: radial-gradient(circle at 30% 30%, var(--red-ball), #c0392b); } .blue-ball { background: radial-gradient(circle at 30% 30%, var(--blue-ball), #2980b9); } .probability-bars { display: flex; flex-direction: column; gap: 0.8rem; margin-top: 1.5rem; } .probability-item { display: flex; align-items: center; } .number-label { width: 30px; text-align: center; font-weight: bold; } .bar-container { flex-grow: 1; height: 24px; background-color: #e0e0e0; border-radius: 12px; overflow: hidden; margin: 0 1rem; } .bar-fill { height: 100%; border-radius: 12px; transition: width 1s ease-out; } .red-fill { background: linear-gradient(to right, #f5b7b1, var(--red-ball)); } .blue-fill { background: linear-gradient(to right, #aed6f1, var(--blue-ball)); } .percentage { width: 50px; text-align: right; font-weight: 500; } .prediction-actions { display: flex; justify-content: center; gap: 1rem; margin-top: 2rem; } .btn { padding: 0.8rem 1.5rem; border-radius: 50px; border: none; font-weight: 600; cursor: pointer; transition: all 0.3s; display: flex; align-items: center; } .btn i { margin-right: 0.5rem; } .btn-primary { background: linear-gradient(to right, var(--primary-green), var(--accent-green)); color: white; } .btn-outline { background: transparent; border: 2px solid var(--accent-green); color: var(--accent-green); } .btn:hover { transform: translateY(-2px); box-shadow: 0 4px 8px var(--shadow-medium); } .disclaimer { font-size: 0.9rem; color: var(--primary-gray); margin-top: 2rem; text-align: center; font-style: italic; } footer { background-color: var(--primary-dark); color: white; padding: 3rem 0; margin-top: auto; } @media (max-width: 768px) { .header-content { flex-direction: column; gap: 1rem; } nav ul { gap: 1rem; flex-wrap: wrap; justify-content: center; } .ball { width: 42px; height: 42px; font-size: 1rem; } } </style> </head> <body> <header> <div class="container"> <div class="header-content"> <div class="logo"> <i class="fas fa-chart-line"></i> 双色球数据分析 </div> <nav> <ul> <li><a href="#"><i class="fas fa-home"></i> 首页</a></li> <li><a href="#"><i class="fas fa-history"></i> 历史数据</a></li> <li><a href="#"><i class="fas fa-calculator"></i> 概率分析</a></li> <li><a href="#"><i class="fas fa-magic"></i> 号码预测</a></li> <li><a href="#"><i class="fas fa-question-circle"></i> 帮助</a></li> </ul> </nav> </div> </div> </header> <main class="container"> <section class="hero"> <h1>双色球数据分析与预测系统</h1> <p>基于历史数据分析和概率模型,提供科学的双色球号码预测服务</p> </section> <section class="data-section"> <h2 class="section-title">下期号码预测</h2> <div class="prediction-section"> <h3>第2025091期预测号码</h3> <p>根据历史数据和算法模型生成的推荐号码(更新于2025年8月10日)</p> <div class="number-balls"> <div class="ball red-ball">03</div> <div class="ball red-ball">11</div> <div class="ball red-ball">17</div> <div class="ball red-ball">22</div> <div class="ball red-ball">28</div> <div class="ball red-ball">31</div> <div class="ball blue-ball">09</div> </div> <div class="prediction-actions"> <button class="btn btn-primary"> <i class="fas fa-sync-alt"></i> 重新生成 </button> <button class="btn btn-outline"> <i class="fas fa-download"></i> 保存号码 </button> </div> </div> <div class="chart-container"> <h3><i class="fas fa-fire"></i> 红球热号分析</h3> <canvas id="redBallChart"></canvas> </div> <div class="chart-container"> <h3><i class="fas fa-snowflake"></i> 蓝球冷号分析</h3> <canvas id="blueBallChart"></canvas> </div> <div class="data-grid"> <div class="data-card"> <h3 class="card-title"><i class="fas fa-star"></i> 高频红球</h3> <div class="probability-bars"> <!-- 红球概率条 --> <div class="probability-item"> <div class="number-label">08</div> <div class="bar-container"> <div class="bar-fill red-fill" style="width: 78%"></div> </div> <div class="percentage">78%</div> </div> <div class="probability-item"> <div class="number-label">17</div> <div class="bar-container"> <div class="bar-fill red-fill" style="width: 72%"></div> </div> <div class="percentage">72%</div> </div> <div class="probability-item"> <div class="number-label">22</div> <div class="bar-container"> <div class="bar-fill red-fill" style="width: 68%"></div> </div> <div class="percentage">68%</div> </div> </div> </div> <div class="data-card"> <h3 class="card-title"><i class="fas fa-tint"></i> 蓝球概率</h3> <div class="probability-bars"> <!-- 蓝球概率条 --> <div class="probability-item"> <div class="number-label">09</div> <div class="bar-container"> <div class="bar-fill blue-fill" style="width: 65%"></div> </div> <div class="percentage">65%</div> </div> <div class="probability-item"> <div class="number-label">05</div> <div class="bar-container"> <div class="bar-fill blue-fill" style="width: 58%"></div> </div> <div class="percentage">58%</div> </div> <div class="probability-item"> <div class="number-label">12</div> <div class="bar-container"> <div class="bar-fill blue-fill" style="width: 52%"></div> </div> <div class="percentage">52%</div> </div> </div> </div> </div> <p class="disclaimer"> <i class="fas fa-exclamation-triangle"></i> 免责声明:本预测基于历史数据分析,不保证中奖概率。彩票有风险,投注需谨慎。 </p> </section> </main> <footer> <div class="container"> <p>© 2023 双色球数据分析系统 | 数据仅供参考</p> </div> </footer> <script> // 红球图表数据 const redBallData = { labels: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33'], datasets: [{ label: '出现频率', data: [12, 18, 22, 15, 19, 14, 20, 28, 16, 13, 25, 17, 11, 19, 16, 14, 26, 15, 18, 12, 17, 24, 16, 13, 19, 15, 20, 23, 14, 17, 21, 16, 12], backgroundColor: '#e74c3c', borderColor: '#c0392b', borderWidth: 1 }] }; // 蓝球图表数据 const blueBallData = { labels: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16'], datasets: [{ label: '出现频率', data: [8, 10, 7, 9, 14, 6, 11, 9, 13, 7, 8, 12, 5, 9, 11, 10], backgroundColor: '#3498db', borderColor: '#2980b9', borderWidth: 1 }] }; // 图表配置 const chartConfig = { type: 'bar', options: { responsive: true, scales: { y: { beginAtZero: true, title: { display: true, text: '出现次数' } } }, plugins: { legend: { display: false } } } }; // 初始化图表 window.onload = function() { const redCtx = document.getElementById('redBallChart').getContext('2d'); new Chart(redCtx, { ...chartConfig, data: redBallData }); const blueCtx = document.getElementById('blueBallChart').getContext('2d'); new Chart(blueCtx, { ...chartConfig, data: blueBallData }); // 添加动画效果 document.querySelectorAll('.ball').forEach(ball => { ball.style.animation = 'popIn 0.6s ease-out'; }); }; // 重新生成按钮功能 document.querySelector('.btn-primary').addEventListener('click', function() { const balls = document.querySelectorAll('.ball'); // 添加消失动画 balls.forEach(ball => { ball.style.animation = 'popOut 0.4s forwards'; }); // 延迟后生成新号码 setTimeout(() => { generateNewNumbers(); balls.forEach(ball => { ball.style.animation = 'popIn 0.6s forwards'; }); }, 500); }); // 生成预测号码 function generateNewNumbers() { const redBalls = []; const blueBall = Math.floor(Math.random() * 16) + 1; // 生成6个不重复的红球 while(redBalls.length < 6) { const num = Math.floor(Math.random() * 33) + 1; if(!redBalls.includes(num)) { redBalls.push(num); } } // 排序红球 redBalls.sort((a, b) => a - b); // 更新显示 const ballElements = document.querySelectorAll('.ball'); for(let i = 0; i < 6; i++) { ballElements[i].textContent = redBalls[i].toString().padStart(2, '0'); } ballElements.textContent = blueBall.toString().padStart(2, '0'); } </script> </body> </html> 以上内容由AI搜集并生成,仅供参考
最新发布
08-10
\textbf{Algorithm 2.} Coarse Global Reconstruction \textbf{Input:} Coarse granular balls $coarse\_balls$ ($r_k > 50px$), SIFT features $F_{sift}$ \textbf{Output:} Global rotations $\{R_i\}$, Normal vectors $\{n_k\}$ \begin{enumerate} \item \textbf{For each} ball $B_k \in coarse\_balls$: \begin{enumerate} \item Compute EWGD descriptor: \begin{itemize} \item $F_{sift} = [f_1, f_2, \dots, f_N] \in \mathbb{R}^{128}$ \item $\xi_{SIFT}^{agg} = \frac{1}{N}\sum_{i=1}^{N} F_{sift}[i, 0:63]$ \quad // Eq.14 (64D) \end{itemize} \item Compute entropy-weighted subblock features: \begin{itemize} \item $\xi_{SUBP}^w = \mathbf{0}_{128}$ \item \textbf{For} $d = 1$ \textbf{to} $64$: \quad // 8×8 subblocks \begin{itemize} \item $w_d = \text{entropy\_weight}(B_k, d)$ \item $\xi_{SUBP}^w \mathrel{+}= w_d \cdot \text{subblock\_feature}(B_k, d)$ \end{itemize} \item $\phi_{EWGD} = \text{concat}(\xi_{SIFT}^{agg}, \xi_{SUBP}^w)$ \quad // Eq.16 (192D) \end{itemize} \item Estimate normal vector: \begin{itemize} \item $P = \{x_1, x_2, \dots, x_N\}$ \quad // 3D points \item $n_k = \text{PCA}(P).\text{min\_eigenvector}$ \end{itemize} \end{enumerate} \item \textbf{Global rotation optimization:} \quad // Eq.17 \begin{itemize} \item Initialize $\{R_i\} = I$ \item \textbf{While not converged}: \begin{itemize} \item $\mathcal{L} = 0$ \item \textbf{For each} edge $(B_i, B_j)$ in topological graph: \begin{itemize} \item $\mathcal{L} \mathrel{+}= \|R_i n_i - R_j n_j\|_2^2$ \end{itemize} \item Update $\{R_i\}$ via Lie algebra optimization \end{itemize} \end{itemize} \item \textbf{Return} $\{R_i\}, \{n_k\}$ \end{enumerate}
08-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值