Frage

Die beiden Funktionen in OpenCV cvLoadImage und cvSaveImage akzeptieren als Argument Dateipfad ist.

Wenn zum Beispiel ein Bild zu speichern, es ist cvSaveImage ( "/ tmp / output.jpg", dstIpl) und schreibt es auf dem Datenträger.

Gibt es eine Möglichkeit, dies einen Puffer bereits im Speicher zu füttern? Also statt einer Festplatte schreibt, wird das Ausgangsbild in Erinnerung sein.

Ich würde auch beide wie dies wissen cvSaveImage und cvLoadImage (lesen und Speicherpuffer schreiben). Dank!


Mein Ziel ist es, die Encoded (jpeg) Version der Datei im Speicher zu speichern. Das Gleiche gilt zu cvLoadImage, ich möchte eine jpeg laden, die in das IplImage Format im Speicher ist.

War es hilfreich?

Lösung

Es gibt ein paar undokumentierte Funktionen in der SVN-Version des libary:

CV_IMPL CvMat* cvEncodeImage( const char* ext, 
                              const CvArr* arr, const int* _params )

CV_IMPL IplImage* cvDecodeImage( const CvMat* _buf, int iscolor )

Die neueste Check-in Meldung besagt, dass sie für die eigene Codierung sind / Dekodierung für bmp, png, ppm und TIFF (Codierung nur).

Alternativ können Sie eine Standard-Bildkodierung Bibliothek verwenden (z libjpeg) und manipulieren die Daten in der IplImage die Eingangsstruktur der Codierung Bibliothek entsprechen.

Andere Tipps

Das ist für mich gearbeitet

// decode jpg (or other image from a pointer)
// imageBuf contains the jpg image
    cv::Mat imgbuf = cv::Mat(480, 640, CV_8U, imageBuf);
    cv::Mat imgMat = cv::imdecode(imgbuf, CV_LOAD_IMAGE_COLOR);
// imgMat is the decoded image

// encode image into jpg
    cv::vector<uchar> buf;
    cv::imencode(".jpg", imgMat, buf, std::vector<int>() );
// encoded image is now in buf (a vector)
    imageBuf = (unsigned char *) realloc(imageBuf, buf.size());
    memcpy(imageBuf, &buf[0], buf.size());
//  size of imageBuf is buf.size();

Ich war über eine C-Version anstelle von C ++ gefragt:

#include <opencv/cv.h>
#include <opencv/highgui.h>

int
main(int argc, char **argv)
{
    char *cvwin = "camimg";

    cvNamedWindow(cvwin, CV_WINDOW_AUTOSIZE);

    // setup code, initialization, etc ...
    [ ... ]

    while (1) {      
        // getImage was my routine for getting a jpeg from a camera
        char *img = getImage(fp);
        CvMat mat;

   // substitute 640/480 with your image width, height 
        cvInitMatHeader(&mat, 640, 480, CV_8UC3, img, 0);
        IplImage *cvImg = cvDecodeImage(&mat, CV_LOAD_IMAGE_COLOR);
        cvShowImage(cvwin, cvImg);
        cvReleaseImage(&cvImg);
        if (27 == cvWaitKey(1))         // exit when user hits 'ESC' key
        break;
    }

    cvDestroyWindow(cvwin);
}

Ich nehme an, Sie in Linux arbeiten. Von libjpeg.doc:

  

Die grobe Skizze eines JPEG   Kompressionsvorgang ist:
  zuteilen   und initialisieren eine JPEG-Komprimierung   Objekt
  Geben Sie das Ziel für   die komprimierten Daten (zB eine Datei)
  einstellen   Parameter für die Kompression, einschließlich   Bildgröße und Farbraum

     

jpeg_start_compress (...);
  während   (Scan-Linien bleiben geschrieben werden)
  jpeg_write_scanlines (...);

     

jpeg_finish_compress (...);
  Freisetzung   das JPEG-Kompression Objekt

Der eigentliche Trick zu tun, was Sie tun möchten, ist eine eigene „Datenziel (oder Quelle) Manager“ bereitzustellen, die in jpeglib.h definiert ist:

struct jpeg_destination_mgr {
  JOCTET * next_output_byte;    /* => next byte to write in buffer */
  size_t free_in_buffer;        /* # of byte spaces remaining in buffer */

  JMETHOD(void, init_destination, (j_compress_ptr cinfo));
  JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo));
  JMETHOD(void, term_destination, (j_compress_ptr cinfo));
};

Im Grunde genommen, dass so einrichten, Ihre Quelle und / oder Ziel sind die Speicherpuffer Sie wollen, und Sie sollten gut gehen.

Als beiseite, könnte dieser Beitrag viel besser sein, aber die libjpeg62 Dokumentation ist, ganz offen gesagt, Pracht. Nur libjpeg62-dev apt-get und libjpeg.doc und Blick auf example.c lesen. Wenn Sie Probleme und nicht etwas bekommen zu arbeiten, schreibt gerade wieder und ich bin sicher, dass jemand in der Lage sein wird, zu helfen.

Alles, was Sie brauchen, Dateien aus dem Speicherpuffer zu laden, ist ein anderer src Manager (libjpeg). Ich habe den folgenden Code in Ubuntu 8.10 getestet.

/******************************** First define mem buffer function bodies **************/
<pre>
/*
 * memsrc.c
 *
 * Copyright (C) 1994-1996, Thomas G. Lane.
 * This file is part of the Independent JPEG Group's software.
 * For conditions of distribution and use, see the accompanying README file.
 *
 * This file contains decompression data source routines for the case of
 * reading JPEG data from a memory buffer that is preloaded with the entire
 * JPEG file.  This would not seem especially useful at first sight, but
 * a number of people have asked for it.
 * This is really just a stripped-down version of jdatasrc.c.  Comparison
 * of this code with jdatasrc.c may be helpful in seeing how to make
 * custom source managers for other purposes.
 */

/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
//include "jinclude.h"
include "jpeglib.h"
include "jerror.h"


/* Expanded data source object for memory input */

typedef struct {
  struct jpeg_source_mgr pub;   /* public fields */

  JOCTET eoi_buffer[2];     /* a place to put a dummy EOI */
} my_source_mgr;

typedef my_source_mgr * my_src_ptr;


/*
 * Initialize source --- called by jpeg_read_header
 * before any data is actually read.
 */

METHODDEF(void)
init_source (j_decompress_ptr cinfo)
{
  /* No work, since jpeg_memory_src set up the buffer pointer and count.
   * Indeed, if we want to read multiple JPEG images from one buffer,
   * this *must* not do anything to the pointer.
   */
}


/*
 * Fill the input buffer --- called whenever buffer is emptied.
 *
 * In this application, this routine should never be called; if it is called,
 * the decompressor has overrun the end of the input buffer, implying we
 * supplied an incomplete or corrupt JPEG datastream.  A simple error exit
 * might be the most appropriate response.
 *
 * But what we choose to do in this code is to supply dummy EOI markers
 * in order to force the decompressor to finish processing and supply
 * some sort of output image, no matter how corrupted.
 */

METHODDEF(boolean)
fill_input_buffer (j_decompress_ptr cinfo)
{
  my_src_ptr src = (my_src_ptr) cinfo->src;

  WARNMS(cinfo, JWRN_JPEG_EOF);

  /* Create a fake EOI marker */
  src->eoi_buffer[0] = (JOCTET) 0xFF;
  src->eoi_buffer[1] = (JOCTET) JPEG_EOI;
  src->pub.next_input_byte = src->eoi_buffer;
  src->pub.bytes_in_buffer = 2;

  return TRUE;
}


/*
 * Skip data --- used to skip over a potentially large amount of
 * uninteresting data (such as an APPn marker).
 *
 * If we overrun the end of the buffer, we let fill_input_buffer deal with
 * it.  An extremely large skip could cause some time-wasting here, but
 * it really isn't supposed to happen ... and the decompressor will never
 * skip more than 64K anyway.
 */

METHODDEF(void)
skip_input_data (j_decompress_ptr cinfo, long num_bytes)
{
  my_src_ptr src = (my_src_ptr) cinfo->src;

  if (num_bytes > 0) {
    while (num_bytes > (long) src->pub.bytes_in_buffer) {
      num_bytes -= (long) src->pub.bytes_in_buffer;
      (void) fill_input_buffer(cinfo);
      /* note we assume that fill_input_buffer will never return FALSE,
       * so suspension need not be handled.
       */
    }
    src->pub.next_input_byte += (size_t) num_bytes;
    src->pub.bytes_in_buffer -= (size_t) num_bytes;
  }
}


/*
 * An additional method that can be provided by data source modules is the
 * resync_to_restart method for error recovery in the presence of RST markers.
 * For the moment, this source module just uses the default resync method
 * provided by the JPEG library.  That method assumes that no backtracking
 * is possible.
 */


/*
 * Terminate source --- called by jpeg_finish_decompress
 * after all data has been read.  Often a no-op.
 *
 * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
 * application must deal with any cleanup that should happen even
 * for error exit.
 */

METHODDEF(void)
term_source (j_decompress_ptr cinfo)
{
  /* no work necessary here */
}


/*
 * Prepare for input from a memory buffer.
 */

GLOBAL(void)
jpeg_memory_src (j_decompress_ptr cinfo, const JOCTET * buffer, size_t bufsize)
{
  my_src_ptr src;

  /* The source object is made permanent so that a series of JPEG images
   * can be read from a single buffer by calling jpeg_memory_src
   * only before the first one.
   * This makes it unsafe to use this manager and a different source
   * manager serially with the same JPEG object.  Caveat programmer.
   */
  if (cinfo->src == NULL) { /* first time for this JPEG object? */
    cinfo->src = (struct jpeg_source_mgr *)
      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
                  SIZEOF(my_source_mgr));
  }

  src = (my_src_ptr) cinfo->src;
  src->pub.init_source = init_source;
  src->pub.fill_input_buffer = fill_input_buffer;
  src->pub.skip_input_data = skip_input_data;
  src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
  src->pub.term_source = term_source;

  src->pub.next_input_byte = buffer;
  src->pub.bytes_in_buffer = bufsize;
}

Dann ist die Verwendung ziemlich einfach. Möglicherweise müssen Sie SIZEOF () mit sizeof () ersetzen. Finden Sie eine Standard-Dekompression Beispiel. Ersetzen Sie einfach „jpeg_stdio_src“ mit „jpeg_memory_src“. Hoffe, das hilft!

Hier ist ein Beispiel in Delphi. Es wandelt eine 24-Bit-Bitmap für die Verwendung mit OpenCV

function BmpToPIplImageEx(Bmp: TBitmap): pIplImage;
Var
  i: Integer;
  offset: LongInt;
  dataByte: PByteArray;  
Begin
  Assert(Bmp.PixelFormat = pf24bit, 'PixelFormat must be 24bit');
  Result := cvCreateImageHeader(cvSize(Bmp.Width, Bmp.Height), IPL_DEPTH_8U, 3);
  cvCreateData(Result);
  for i := 0 to Bmp.height - 1 do
  Begin        
    offset   := longint(Result.imageData) + Result.WidthStep * i;
    dataByte := PByteArray(offset);    
    CopyMemory(dataByte, Bmp.Scanline[i], Result.WidthStep);
  End;
End;

Dies ist eine indirekte Antwort ...

In der Vergangenheit habe ich direkt verwendet libpng und libjpeg direkt, dies zu tun. Sie haben einen Low-Level-API genug, dass Sie Speicherpuffer anstelle von Dateipuffer zum Lesen und Schreiben verwenden können.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top