우리는 모두 Instagram이나 Snapchat 또는 다른 애플리케이션에서 증강된 얼굴 텍스처를 사용했습니다. 얼굴에 ar 개체를 시도할 수 있는 샘플 앱을 개발하려고 합니다. 지금까지 그 물체를 얼굴에 표시할 수 있었습니다.
그런 다음 사용자가 개체를 다른 개체로 전환할 수 있도록 아래 항목 목록을 표시합니다( instagram / snapchat에서 새 필터를 시도하는 것과 유사).
다음은 한 개체에 대한 기본 코드입니다.
Texture.builder()
.setSource(this, R.drawable.fox_face_mesh_texture)
.build()
.thenAccept(texture -> faceMeshTexture1 = texture);
ArSceneView sceneView = arFragment.getArSceneView();
sceneView.setCameraStreamRenderPriority(Renderable.RENDER_PRIORITY_FIRST);
Scene scene = sceneView.getScene();
scene.addOnUpdateListener(new Scene.OnUpdateListener() {
@Override
public void onUpdate(FrameTime frameTime) {
if (faceMeshTexture1 == null)
return;
Collection<AugmentedFace> faceList =
sceneView.getSession().getAllTrackables(AugmentedFace.class);
for (AugmentedFace face : faceList) {
if (!faceNodeMap.containsKey(face)) {
AugmentedFaceNode faceNode = new AugmentedFaceNode(face);
faceNode.setParent(scene);
faceNode.setFaceMeshTexture(faceMeshTexture1);
faceNodeMap.put(face, faceNode);
}
}
Iterator<Map.Entry<AugmentedFace, AugmentedFaceNode>> iter =
faceNodeMap.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<AugmentedFace, AugmentedFaceNode> entry = iter.next();
AugmentedFace face = entry.getKey();
if (face.getTrackingState() == TrackingState.STOPPED) {
AugmentedFaceNode faceNode = entry.getValue();
faceNode.setParent(null);
iter.remove();
}
}
}
});
내가 시도한 것
In 버튼 onClick - 다음을 수행하여 새 텍스처를 만들었습니다. Texture.builder().setSource ...
1) for 루프를 작성하려고 했지만 for (AugmentedFace face : faceList) { ... }
아무 것도 하지 않았습니다.
2) onUpdate()
기능 의 전체 내용을 포함시키려고 노력했습니다 . 하지만 그것도 효과가 없었습니다.
3) 그런 다음 2개의 텍스처를 만들고 부울 변수를 사용하여 부울 값( 버튼 클릭 시)을 반대로 하여 해당 텍스처( onUpdate 메서드에서)를 전환하려고 했습니다. 다음과 같이 보입니다.
Texture.builder()
.setSource(this, R.drawable.fox_face_mesh_texture)
.build()
.thenAccept(texture -> faceMeshTexture1 = texture);
Texture.builder()
.setSource(this, R.drawable.red_lipstick)
.build()
.thenAccept(texture -> faceMeshTexture2 = texture);
ArSceneView sceneView = arFragment.getArSceneView();
sceneView.setCameraStreamRenderPriority(Renderable.RENDER_PRIORITY_FIRST);
Scene scene = sceneView.getScene();
scene.addOnUpdateListener(new Scene.OnUpdateListener() {
@Override
public void onUpdate(FrameTime frameTime) {
if (faceMeshTexture1 == null || faceMeshTexture2 == null)
return;
Collection<AugmentedFace> faceList =
sceneView.getSession().getAllTrackables(AugmentedFace.class);
for (AugmentedFace face : faceList) {
if (!faceNodeMap.containsKey(face)) {
AugmentedFaceNode faceNode = new AugmentedFaceNode(face);
faceNode.setParent(scene);
if( !redOrFox ) {
faceNode.setFaceMeshTexture(faceMeshTexture1);
Log.d(TAG, "onUpdate: redorfox:" + redOrFox);
}
else {
faceNode.setFaceMeshTexture(faceMeshTexture2);
Log.d(TAG, "onUpdate: else redorfox:" + redOrFox);
}
faceNodeMap.put(face, faceNode);
}
}
Iterator<Map.Entry<AugmentedFace, AugmentedFaceNode>> iter = faceNodeMap.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<AugmentedFace, AugmentedFaceNode> entry = iter.next();
AugmentedFace face = entry.getKey();
if (face.getTrackingState() == TrackingState.STOPPED) {
AugmentedFaceNode faceNode = entry.getValue();
faceNode.setParent(null);
iter.remove();
}
}
}
});
mBtnBlueLip.setOnClickListener(v -> {
redOrFox = true;
Log.d(TAG, "onCreate: blue clicked");
});
mBtnRedLip.setOnClickListener(v -> {
redOrFox = false;
Log.d(TAG, "onCreate: red clicked");
});
하지만 그것도 아무 소용이 없었다. 이 시점에서 나는 무엇을 해야 할지 막막합니다. 증강 얼굴과 몇 가지 샘플 앱에 관한 문서는 거의 없습니다(그러나 Kotlin에는 있음). 비슷한 질문 이 발견되었지만(3D의 경우) 답변이 없습니다.
편집: 또한 디버깅 후에도 onUpdate 함수가 한 번만 호출되는 것처럼 보입니다. 여기에서 무슨 일이 일어나고 있는지 이해하지 못합니까?
Kristina Simakova가 개발한 이 kotlin 앱 에서 해결책을 찾았 습니다 .
올바른 길을 가고 있었던 것 같습니다. 내가 놓친 것은 face
객체가 이미 faceList
배열에 있으므로 if 조건에 전혀 들어가지 않는다는 것입니다.
if (!faceNodeMap.containsKey(face)) { ... }
다른 사람이 없었기 때문에 아무 일도 일어나지 않았습니다.
솔루션에는 버튼이 클릭되었는지 여부를 확인하는 또 다른 부울 변수가 있습니다!
Boolean isFox = false, changeModel = false;
...
scene.addOnUpdateListener(frameTime -> {
...
for (AugmentedFace face : faceList) {
if (!faceNodeMap.containsKey(face)) {
AugmentedFaceNode faceNode = new AugmentedFaceNode(face);
faceNode.setParent(scene);
faceNode.setFaceMeshTexture(faceMeshTexture1);
faceNodeMap.put(face, faceNode);
}
else if (changeModel) { // check whether we want to change texture
if(isFox)
faceNodeMap.get(face).setFaceMeshTexture(faceMeshTexture1);
else
faceNodeMap.get(face).setFaceMeshTexture(faceMeshTexture2);
}
}
changeModel = false; // after the for loop ends
...
mBtnBlueLip.setOnClickListener(v -> {
isFox = true;
changeModel = true;
});
mBtnRedLip.setOnClickListener(v -> {
changeModel = true;
isFox = false;
});
Kristina도 비슷한 접근 방식을 사용했습니다. 앱을 테스트 중이고 텍스처가 2개뿐이므로 부울 변수를 사용했습니다 isFox
. 또한 텍스처 배열을 유지하고 faceMeshTexture
어떤 버튼을 클릭했는지에 따라 값을 가져오는 변수 하나만 유지할 수 있습니다 .
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다