EmguCV - как указать качество jpeg при сохранении изображения?

Я сохраняю изображение в формате jpeg, используя следующий код C# EmguCV:

Emgu.CV.Image<Gray, byte> image
...
image.Save("imageName.jpg");

Но изображение хранится в крайне низком качестве (1 цветной квадрат на 8x8 пикселей).

Когда я сохраняю bmp, все в порядке:

Emgu.CV.Image<Gray, byte> image
...
image.Save("imageName.bmp");

Как повысить качество jpeg при использовании Emgu.Cv.Image.Save или нужно вызвать другую функцию? Почему качество по умолчанию такое низкое?

Пытался спросить на форуме EmguCV, но он недоступен.


person sergtk    schedule 27.10.2011    source источник
comment
Привет, от имени EMGU я извиняюсь за то, что сайт не работает, но я всегда троллю здесь и отвечаю на любые вопросы, с которыми могу помочь. Ваше здоровье   -  person Chris    schedule 27.10.2011
comment
@ Крис Большое спасибо. Теперь я знаю, к кому я могу обратиться. Предлагаем стабильную работу сайта!   -  person sergtk    schedule 31.10.2011


Ответы (4)


EMGU имеет только image.Save(имя файла), поэтому вы должны использовать метод .Net для сохранения изображения. Этот код взят из здесь. Я разделил код для простоты, этот код открывает файл, а затем пытается его сохранить. Это интересующая вас функция saveJpeg(SaveFile.FileName, img.ToBitmap(), 100);. На основе функции saveJpeg(string path, Bitmap img, длинное качество).

open.Filter = "Image Files (*.tif; *.dcm; *.jpg; *.jpeg; *.bmp)|*.tif; *.dcm; *.jpg; *.jpeg; *.bmp";
if (open.ShowDialog() == DialogResult.OK)
{
    Image<Bgr, Byte> img = new Image<Bgr, Byte>(open.FileName);
    SaveFileDialog SaveFile = new SaveFileDialog();
    if (SaveFile.ShowDialog() == DialogResult.OK)
    {
        saveJpeg(SaveFile.FileName, img.ToBitmap(), 100);
    }
}

Теперь, чтобы получить код для этой функции, полученный из следующего, вы можете скопировать и вставить его в свой проект, не забудьте использовать оператор в верхней части вашего кода.

using System.Drawing.Imaging;

private void saveJpeg(string path, Bitmap img, long quality)
{
    // Encoder parameter for image quality

    EncoderParameter qualityParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);

    // Jpeg image codec
    ImageCodecInfo jpegCodec = this.getEncoderInfo("image/jpeg");

    if (jpegCodec == null)
    return;

    EncoderParameters encoderParams = new EncoderParameters(1);
    encoderParams.Param[0] = qualityParam;

    img.Save(path, jpegCodec, encoderParams);
}

private ImageCodecInfo getEncoderInfo(string mimeType)
{
    // Get image codecs for all image formats
    ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();

    // Find the correct image codec
    for (int i = 0; i < codecs.Length; i++)
    if (codecs[i].MimeType == mimeType)
    return codecs[i];
    return null;
}

Это лучший способ для EMGU, если вы застряли, дайте мне знать.

Надеюсь это поможет,

Крис

person Chris    schedule 27.10.2011
comment
Кажется, подходит для меня. благодаря. В любом случае, с EmguCV случилось что-то странное - почему он сохраняет jpeg с таким низким качеством? Я не могу понять. - person sergtk; 28.10.2011
comment
Я не могу точно сказать, что я не первый раз сталкиваюсь с такими плохими функциями сохранения изображений, ведь некоторые дорогостоящие системы MVS используют такое же качество сжатия. Я подниму этот вопрос, однако он может не попасть в новую версию, поскольку этот метод довольно специфичен для платформы. Рад, что это помогло, хотя, Ура - person Chris; 28.10.2011
comment
Я нашел, как воспроизвести столь странное поведение. Если приложение запущено под VS2010 и каталог bin содержит highgui210d.dll, проблема появляется, если я удаляю highgui210d.dll, все работает нормально... - person sergtk; 28.10.2011

Основываясь на ответе Криса, если кому-то здесь интересно, это простое расширение;

using System;
using System.Linq;
using System.Drawing.Imaging;
using Emgu.CV.Structure;

public static class EmguImageSave
{
    /// <summary>
    /// Save a jpeg image with a specified quality
    /// </summary>
    /// <param name="path">Name of the file to which to save the image</param>
    /// <param name="quality">Byte that specifies JPEG Quality of the image encoder</param>
    public static void Save( this Emgu.CV.Image<Bgr, Byte> img, string filename, double quality )
    {
        var encoderParams = new EncoderParameters( 1 );
        encoderParams.Param[0] = new EncoderParameter(
            System.Drawing.Imaging.Encoder.Quality,
            (long)quality
            );

        var jpegCodec = (from codec in ImageCodecInfo.GetImageEncoders()
                         where codec.MimeType == "image/jpeg"
                         select codec).Single();

        img.Bitmap.Save( filename, jpegCodec, encoderParams );
    }
}

Использование;

var fname = 0;
while( true )
{
    try
    {
        var img = capture.QueryFrame();
        img.Save( String.Format( @"c:\rec\{0}.jpg", ++fname), 100 );
    } catch( Exception ) { break; }
}
person expelledboy    schedule 06.07.2012

Вот как я поступил с Emgu CV:

CvInvoke.Imwrite(path, cvImage, new KeyValuePair<ImwriteFlags, int> (ImwriteFlags.JpegQuality, quality));
person Alon Catz    schedule 03.09.2017

Попробуй это. И почему бы вам не использовать старый и добрый документ OpenCV http://opencv.itseez.com?

int quality = 100; // 0 - low, 100 - best
image.Save("imageName.bmp", CV_IMWRITE_JPEG_QUALITY, quality);
person Sam    schedule 27.10.2011
comment
Извините, но это невозможно с EMGU, и ссылка OpenCV не применима. - person Chris; 27.10.2011