我利用这个方法检测应用存在花屏问题,误判率居高不下,请问如何修改降低误判率 def check_screen(self):
# 获取屏幕截图并保存为临时文件
screenshot = self.driver.get_screenshot_as_png()
screenshot_path = "temp_screenshot.png"
with open(screenshot_path, 'wb') as f:
f.write(screenshot)
# ------------------------ 新花屏检测逻辑(优化版) ------------------------
img_cv = cv2.imread(screenshot_path)
height, width, _ = img_cv.shape
total_pixels = height * width
# 动态调整区域划分(根据屏幕宽高比优化)
aspect_ratio = width / height
if 1.5 <= aspect_ratio <= 2.0: # 常见手机竖屏比例
num_rows, num_cols = 4, 8 # 更密集的纵向划分
elif aspect_ratio > 2.0: # 超宽屏
num_rows, num_cols = 3, 12
else: # 其他比例(如平板横屏)
num_rows, num_cols = 3, 6
block_h, block_w = height // num_rows, width // num_cols
block_list = []
# 特征参数(通过历史数据校准的阈值)
FEATURE_THRESHOLDS = {
'variance': 150, # 灰度方差阈值(过低=均匀异常)
'entropy': 2.2, # 灰度熵阈值(过低=颜色集中)
'edge_density': 0.08, # 边缘密度阈值(过高=条纹/噪点)
'contrast': 40 # 对比度阈值(过低=模糊异常)
}
for row in range(num_rows):
for col in range(num_cols):
# 计算区域坐标(防止越界)
y_start = max(0, row * block_h)
y_end = min(height, (row + 1) * block_h)
x_start = max(0, col * block_w)
x_end = min(width, (col + 1) * block_w)
block = img_cv[y_start:y_end, x_start:x_end]
gray = cv2.cvtColor(block, cv2.COLOR_BGR2GRAY)
h, w = gray.shape
block_area = h * w
# 特征1:灰度方差(衡量亮度变化)
variance = np.var(gray)
# 特征2:灰度熵(衡量颜色分布混乱度)
hist = cv2.calcHist([gray], [0], None, [256], [0, 256]).flatten()
prob = hist / (block_area + 1e-7) # 防止除零
entropy = -np.sum(prob * np.log(prob + 1e-7)) # 平滑处理
# 特征3:边缘密度(Canny边缘检测)
edges = cv2.Canny(gray, 50, 150) # 固定阈值(可根据实际调整)
edge_pixels = np.count_nonzero(edges)
edge_density = edge_pixels / block_area
# 特征4:对比度(最大灰度差)
contrast = np.max(gray) - np.min(gray)
# 记录所有特征值
block_features = {
'variance': variance,
'entropy': entropy,
'edge_density': edge_density,
'contrast': contrast,
'area': block_area,
'coords': (x_start, y_start, x_end, y_end)
}
block_list.append(block_features)
# 计算全局特征基准(用于动态阈值)
all_variances = [b['variance'] for b in block_list]
all_entropies = [b['entropy'] for b in block_list]
global_variance_mean = statistics.mean(all_variances)
global_entropy_mean = statistics.mean(all_entropies)
# 动态调整阈值(基于全局均值±2倍标准差)
dynamic_thresholds = {
'variance': global_variance_mean - 1.5 * np.std(all_variances), # 偏离均值1.5σ视为异常
'entropy': global_entropy_mean - 1.5 * np.std(all_entropies)
}
# 筛选疑似花屏区域(满足任意2个以上特征异常)
flower_blocks = []
for block in block_list:
var_anomaly = block['variance'] < dynamic_thresholds['variance']
entropy_anomaly = block['entropy'] < dynamic_thresholds['entropy']
edge_anomaly = block['edge_density'] > FEATURE_THRESHOLDS['edge_density']
contrast_anomaly = block['contrast'] < FEATURE_THRESHOLDS['contrast']
# 至少满足2个异常特征才标记
if sum([var_anomaly, entropy_anomaly, edge_anomaly, contrast_anomaly]) >= 2:
# 排除过小区域(面积小于总屏幕的0.5%)
if block['area'] >= (total_pixels * 0.005):
flower_blocks.append(block)
# 计算花屏区域总面积占比(超过5%判定为花屏)
flower_area = sum(b['area'] for b in flower_blocks)
is_flower_screen = (flower_area / total_pixels) > 0.1
# 使用 PIL 处理图像,检测黑屏和白屏
img_pil = Image.open(screenshot_path).convert('RGBA')
color, total = (0, 0, 0), 0
for count, (r, g, b, a) in img_pil.getcolors(img_pil.size[0] * img_pil.size[1]):
if a != 0: # 只处理透明度不为 0(即可见)的像素点
color = (color[0] + r * count, color[1] + g * count, color[2] + b * count)
total += count
if total > 0:
dominant_color = (int(color[0] / total), int(color[1] / total), int(color[2] / total))
mean = statistics.mean(list(dominant_color))
is_black_screen = mean < 10 # 判断黑屏
is_white_screen = mean > 254 # 判断白屏
else:
is_black_screen = True
is_white_screen = False
# 保存问题截图(任意异常触发保存)
if is_flower_screen or is_black_screen or is_white_screen:
save_dir = os.path.join('D:', 'screenshot')
os.makedirs(save_dir, exist_ok=True)
shutil.copy(screenshot_path, os.path.join(save_dir, 'problem_screenshot.png'))
# 删除临时截图文件
os.remove(screenshot_path)
return is_flower_screen, is_black_screen, is_white_screen