问题描述
我和我的队友正在做一个项目,我们使用 OpenCV 检测 ArUco 标记并使用 Rajawali(OpenGL ES 包装库,在 github 上)在检测到的标记上渲染 3D 对象。
我们知道我们的检测是正确的,因为我们使用 drawAxis
方法测试它并且它非常稳定和准确。所以这应该排除校准和检测错误。
这是在我的笔记本电脑上的标记上绘制的轴的外观。这不是视频,但相信我,它在我尝试过的大多数距离/角度配置中都是一致的,所以我认为它非常好。
这除了渲染方法外什么也没有留下,它会产生非常错误的结果。 一旦我们开始尝试在标记上渲染对象:
- 方向被扼杀了。模型相对于标记很少正确定向。感觉它几乎没有旋转,只是漂浮在屏幕上。
- 翻译也被扼杀了。模型永远不会“粘”在标记上,而是几乎总是随着相机的中心移动(好像它被锁定到相机,而不是标记)。
- 模型轻微抖动,不稳定。完全不像轴。即使我拿着相机完全静止。 3 是一个我们可能可以忍受的问题,但 1 和 2 太多了。 这是呈现对象的方法,它是用 Java 编写的,但我认为非 Java 用户也可以使用它。 这是检测标记的方式(rvec 和 tvec 值):
/**
* This method takes a gray frame,detects the markers
* and stores their corners,rvecs,tvecs and ids,* then updates the detectedMarkers list with the new markers detected.
* @param frameGray
*/
public void markerDetection(Mat frameGray)
{
ids = new Mat();
corners = new ArrayList<>();
Aruco.detectMarkers(frameGray,markerDictionary,corners,ids);
List<MarkerData> newDetectedMarkers = new ArrayList<>();
if(ids.size().height > 0)
{
rvecs = new Mat();
tvecs = new Mat();
Aruco.estimatePoseSingleMarkers(corners,markerLength,cameraMatrix,distortionCoef,tvecs);
for(int i=0; i<ids.size().height; i++)
{
double[] rvecArray = new double[]{
rvecs.get(i,0)[0],rvecs.get(i,0)[1],0)[2]};
double[] tvecArray = new double[]{
tvecs.get(i,tvecs.get(i,0)[2]};
MarkerData newMarker = new MarkerData(rvecArray,tvecArray,corners.get(i),(int)ids.get(i,0)[0]);
newDetectedMarkers.add(newMarker);
}
}
updateDetectedMarkers(newDetectedMarkers);
}
渲染是这样完成的:
@Override
protected void onRender(long elapsedRealtime,double deltaTime) {
super.onRender(elapsedRealtime,deltaTime);
getCurrentScene().clearChildren();
List<MarkerData> markerData = markerDetector.getDetectedMarkers();
for (MarkerData marker : markerData) {
try {
int id = R.raw.monkey;
LoaderOBJ parser = new LoaderOBJ(mContext.getResources(),mTextureManager,id);
parser.parse();
Object3D object = parser.getParsedobject();
object.setMaterial(defaultMaterial);
object.setScale(0.3);
Mat rvec = marker.getRvec(); // 3x1 Mat
Mat tvec = marker.getTvec(); // 3x1 Mat
object.setRotation(new Vector3(rvec.get(0,rvec.get(1,rvec.get(2,0)[0]));
object.setPosition(new Vector3(tvec.get(0,tvec.get(1,tvec.get(2,0)[0]));
getCurrentScene().addChild(object);
} catch (ParsingException e) {
e.printstacktrace();
}
}
}
markerData 是一个 MarkerData 对象列表,其中包含每个检测到的标记的 rvec
、tvec
、corners
和 id
。
object 是解析后的 3D 对象,在本例中它是 Suzanne 猴子对象。
我们获取与当前标记关联的 rvec 和 tvec,并将它们存储在 rvec
和 tvec
中。
我们使用它们来设置旋转和设置对象的位置,剩下的就交给 rajawali 了。
我确信我们在这里和那里都缺少一些线性代数的魔力,但我们在那个领域并不是很精通。我们缺少什么?我们怎样才能做到这一点?帮助将不胜感激。
这是我的猜测,我希望这是一个很好的猜测。无论如何,任何人都可以提供帮助。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)