2016-06-15 2 views
3

Je suis en train de convertir un cadre de taille 1280x720 dans Bitmap en utilisant javacv AndroidFrameConverter et il faut beaucoup de temps pour convertir. Voici l'exemple de code de conversion.Convertir un cadre de javacv Dans Bitmap en utilisant AndroidFrameConverter

FrameGrabber grabber = new FFmpegFrameGrabber(videoUrl); 
frame = grabber.grab(); 
AndroidFrameConverter converter = new AndroidFrameConverter(); 
Bitmap originalBitmap = converter.convert(frame); 

Y at-il une autre solution qui est plus rapide que cela?

+0

La conversion de bitmap est une tâche lourde. Il faudra donc du temps pour la convertir. La chose est quelle opération devez-vous faire après la conversion en bitmap? –

+0

Je veux dessiner quelques superpositions sur bitmap après la conversion. –

+0

puis son bon.Javacv fournit cette fonctionnalité via FrameFilter dans lequel vous pouvez utiliser la commande ffmpeg pour dessiner une superposition sans convertir en bitmap.J'ajouter un exemple de code pour FrameFilter, puis vous pouvez jouer avec cela pour atteindre le résultat souhaité. –

Répondre

1

Vous pouvez utiliser ce code et changer le filtre en fonction de vos besoins.

public class FilterAsync extends AsyncTask { 

    private FFmpegFrameGrabber VIDEO_GRABBER; 
    private FFmpegFrameRecorder videoRecorder; 
    private File file = new File(Environment.getExternalStorageDirectory() + "/Download/Abc.mp4"); 
    private Context mContext; 
    private FFmpegFrameFilter filter; 
    private boolean isTrue = false; 
    private ArrayList<String> videoPaths; 
    private File myDirectory; 


    public FilterAsync(Context context) { 
     mContext = context; 
     VIDEO_GRABBER = new FFmpegFrameGrabber(file); 
     myDirectory = new File(Environment.getExternalStorageDirectory() + "/Folder/"); 
     if (!myDirectory.exists()) { 
      myDirectory.mkdirs(); 
     } 
     videoPaths = new ArrayList<>(); 
    } 


    @Override 
    protected void onPreExecute() { 
     super.onPreExecute(); 

    } 

    @Override 
    protected Object doInBackground(Object[] params) { 
     Frame tempVideoFrame; 
     try { 
      VIDEO_GRABBER.start(); 
      initVideoRecorder(myDirectory + "/video" + System.currentTimeMillis() + ".mp4"); 
      filter.start(); 
      while (VIDEO_GRABBER.grab() != null) { 
       tempVideoFrame = VIDEO_GRABBER.grabImage(); 
       if (tempVideoFrame != null) { 
        filter.push(tempVideoFrame); 
        tempVideoFrame = filter.pull(); 
        videoRecorder.record(tempVideoFrame); 
       } 
      } 
      videoRecorder.stop(); 
      filter.stop(); 
      videoRecorder.release(); 
      VIDEO_GRABBER.stop(); 
      VIDEO_GRABBER.release(); 
     } catch (FrameGrabber.Exception e) { 
      e.printStackTrace(); 
     } catch (FrameRecorder.Exception e) { 
      e.printStackTrace(); 
     } catch (FrameFilter.Exception e) { 
      e.printStackTrace(); 
     } 

     return null; 
    } 


    @Override 
    protected void onPostExecute(Object o) { 
     super.onPostExecute(o); 
    } 


    private void initVideoRecorder(String path) { 
     try { 
      filter = new FFmpegFrameFilter("transpose=clock ,crop=w=640:h=480:x=0:y=0", VIDEO_GRABBER.getImageWidth(), VIDEO_GRABBER.getImageHeight()); 

      videoRecorder = FFmpegFrameRecorder.createDefault(path, VIDEO_GRABBER.getImageWidth(), VIDEO_GRABBER.getImageHeight()); 
      videoRecorder.setAudioChannels(VIDEO_GRABBER.getAudioChannels()); 
      videoRecorder.start(); 
     } catch (FrameRecorder.Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+0

il donne des avertissements et exception: Aucune conversion colorspace accélérée trouvé de yuv420p à BGR24. –

+0

Il doit y avoir au problème ur son côté fonctionne parfaitement sur mon côté. Montre moi mes dépendances pour javacv –

+0

compile 'org.bytedeco: javacpp: 1.1' compile 'org.bytedeco: javacv: 1.1' compile 'org.bytedeco.javacpp-presets: ffmpeg: 2.8.1-1.1' compile 'org.bytedeco.javacpp-presets: ffmpeg: 2.8.1-1.1: android-arm' compile 'org.bytedeco.javacpp-presets: ffmpeg: 2.8.1-1.1: android-x86 ' compiler' org.bytedeco.javacpp-préréglages: opencv: 3.0.0-1.1: android-bras ' compiler' org.bytedeco.javacpp-préréglages: opencv: 3.0.0-1.1: android- x86 ' –

0

Frame retourné par FrameGrabber.grab() est javacv spécifique, Bitmap est Android spécifique, je doute qu'il y ait une méthode de convertion plus rapide entre les deux parce qu'ils ne savent pas et les deux étant optimisés pour leur propre usage, ils ne peuvent pas optimiser un processus de conversion entre les deux formats de données.

Vous déménagez 1280 * 720 * 4 octets, environ 3,6 Mo par image, il est beaucoup plus pour les appareils mobiles, surtout compte tenu de l'allocation de mémoire.

Je doute que vous trouverez un autre outil de conversion sans échanger javacv pour quelque chose d'autre - vous ne pouvez pas imaginer un outil spécialement conçu pour convertir Frame de javacv en Android Bitmap pour remplacer les méthodes intégrées.

En outre, AndroidFrameConverter.convert() est déjà assez intelligent - il crée le Bitmap seulement pour la première fois ou si la spécification a changé (comme la taille, etc.), alors il suffit de copier les octets.

Alors heureusement, il a la possibilité de réutiliser une fois créé Bitmap par exemple, FFmpegFrameGrabber a aussi cette capacité, si le premier terme, ils vont créer chacun un objet approprié, mais à partir du deuxième cadre sur devraient réutiliser les objets qu'ils ont - de cette façon au moins, aucune allocation de mémoire inutile ne se produira, ce qui tue les performances sur les appareils mobiles. Cela signifie que la conversion de nombreux cadres en moyenne devrait être beaucoup plus rapide que la conversion seule image - il suffit de ne pas créer de nouvelles instances de la carte d'acquisition et d'un convertisseur pour chaque trame.

La parallélisation à l'aide de GPU est peut-être possible - créez un Bitmap manuellement, partitionnez le tampon Frame et définissez les pixels du Bitmap en parallèle. Je n'ai jamais fait quelque chose comme ça, donc je ne peux pas vraiment en dire plus. Gardez juste à l'esprit que les algorithmes parallèles ont leur propre surcharge et ne sont pas toujours plus rapides que les algorithmes séquentiels. Et je ne suis pas sûr de savoir comment la programmation GPU portable est. La mise en parallèle à l'aide du processeur ne vaut pas la peine d'être essayée - combien de cœurs ont des périphériques actuels? 4? Les frais généraux devraient être plus que le gain.