基于tfjs-models/coco-ssd的目标识别应用:中心十字标记实现求助
目标识别应用中心十字标记实现问题
我正在开发一款基于tfjs-models/coco-ssd的目标识别应用,已经完成目标边框绘制,但中心十字标记功能一直无法实现。原本想通过添加两个半尺寸内部盒子来画十字,但这个方案没生效,求更简便的实现方法和当前代码的修改建议。
现有代码
样式组件代码
const TargetBox = styled.div` position: absolute; left: ${({ x }) => x + "px"}; top: ${({ y }) => y + "px"}; width: ${({ width }) => width + "px"}; height: ${({ height }) => height + "px"}; left2: ${({ x2 }) => x2 / 2+ "px"}; top2: ${({ y2 }) => y2 / 2 + "px"}; width2: ${({ width2 }) => width2 / 2 + "px"}; height2: ${({ height2 }) => height2 / 2 + "px"}; `
逻辑计算代码
const normalizePredictions = (predictions, imgSize) => { if (!predictions || !imgSize || !imageRef) return predictions || []; return predictions.map((prediction) => { const { bbox } = prediction; const oldX = bbox[0]; const oldY = bbox[1]; const oldWidth = bbox[2]; const oldHeight = bbox[3]; const imgWidth = imageRef.current.width; const imgHeight = imageRef.current.height; const x = (oldX * imgWidth) / imgSize.width; const y = (oldY * imgHeight) / imgSize.height; const width = (oldWidth * imgWidth) / imgSize.width; const height = (oldHeight * imgHeight) / imgSize.height; const x2 = (oldX * imgWidth / 2) / imgSize.width; const y2 = (oldY * imgHeight / 2) / imgSize.heigh; const width2 = (oldWidth * imgWidth / 2) / imgSize.width; const height2 = (oldHeight * imgHeight / 2) / imgSize.height; return { ...prediction, bbox: [x, y, width, height, x2, y2, width2, height2] }
效果对比
- 当前效果:仅显示目标边框,无中心十字标记
- 期望效果:目标边框中心显示十字标记
解决方案与代码修改建议
1. 当前代码问题分析
- 样式错误:CSS不存在
left2、top2这类自定义属性,无法被浏览器识别,自定义样式变量需用--变量名格式,或直接通过位置计算实现。 - 逻辑计算错误:
y2计算中imgSize.heigh是拼写错误,应为imgSize.height;且半尺寸盒子的思路本身绕远,中心十字无需额外盒子,直接计算目标框中心坐标即可。
2. 简便实现方案(CSS伪元素)
无需修改逻辑计算代码,仅通过CSS伪元素在目标框中心绘制十字,代码最简洁:
const TargetBox = styled.div` position: absolute; left: ${({ x }) => x + "px"}; top: ${({ y }) => y + "px"}; width: ${({ width }) => width + "px"}; height: ${({ height }) => height + "px"}; border: 2px solid red; /* 目标边框样式 */ /* 横向十字线 */ &::before { content: ''; position: absolute; width: 20px; height: 2px; background-color: red; left: calc(50% - 10px); top: 50%; transform: translateY(-50%); } /* 纵向十字线 */ &::after { content: ''; position: absolute; width: 2px; height: 20px; background-color: red; left: 50%; top: calc(50% - 10px); transform: translateX(-50%); } `
3. 简化后的逻辑计算代码
不需要额外计算x2、y2等参数,保留原有bbox的四个值即可:
const normalizePredictions = (predictions, imgSize) => { if (!predictions || !imgSize || !imageRef) return predictions || []; return predictions.map((prediction) => { const { bbox } = prediction; const oldX = bbox[0]; const oldY = bbox[1]; const oldWidth = bbox[2]; const oldHeight = bbox[3]; const imgWidth = imageRef.current.width; const imgHeight = imageRef.current.height; const x = (oldX * imgWidth) / imgSize.width; const y = (oldY * imgHeight) / imgSize.height; const width = (oldWidth * imgWidth) / imgSize.width; const height = (oldHeight * imgHeight) / imgSize.height; return { ...prediction, bbox: [x, y, width, height] }; }); };
4. 备选方案(子元素实现)
如果不想用伪元素,可在TargetBox内部添加两个子元素作为十字线条:
// 组件渲染部分 {normalizedPredictions.map((pred, idx) => ( <TargetBox key={idx} x={pred.bbox[0]} y={pred.bbox[1]} width={pred.bbox[2]} height={pred.bbox[3]} > <div className="cross-horizontal"></div> <div className="cross-vertical"></div> </TargetBox> ))}
对应的样式:
const TargetBox = styled.div` position: absolute; left: ${({ x }) => x + "px"}; top: ${({ y }) => y + "px"}; width: ${({ width }) => width + "px"}; height: ${({ height }) => height + "px"}; border: 2px solid red; .cross-horizontal { position: absolute; width: 20px; height: 2px; background: red; left: 50%; top: 50%; transform: translate(-50%, -50%); } .cross-vertical { position: absolute; width: 2px; height: 20px; background: red; left: 50%; top: 50%; transform: translate(-50%, -50%); } `
内容的提问来源于stack exchange,提问作者Richardo
相关产品推荐
相关产品推荐

