Сохранение растрового изображения из переменной дает "недопустимый параметр" - PullRequest
0 голосов
/ 10 июля 2020

Мне нужно сохранить на диск изображение, полученное с веб-камеры, между 5 и 10 секундами go с момента, когда команда «сохранить» поступает через последовательный порт.

Чтобы попасть туда, У меня веб-камера входит в pictureBox.Image (с использованием opencv4), а затем 2 переменные Bitmap. Каждые 5 секунд срабатывает таймер, и Stored_bitmap_2 = Stored_bitmap_1, затем Stored_bitmap_1 = (bitmap) pictureBox.Image.

Когда поступает правильная последовательная команда, я пытаюсь Stored_image_2.Save ("C: \ Users \ GreenWorld \ Desktop \ test.jpg", System.Drawing.Imaging.ImageFormat.Jpeg); и я получаю ошибку во время выполнения недопустимого параметра.

Когда я делаю то же самое в автономном проекте с некоторыми кнопками (внутри обработчика событий нажатия кнопки), это срабатывает каждый раз.

Когда я делаю это внутри обработчика serialPort_DataReceived, я получаю всевозможные межпоточные ошибки. Итак, я переместил попытку сохранения в отдельную подпрограмму, и это исправило это, но теперь это.

Я ни в коем случае не профессиональный программист, я инженер с простой проблемой и обычно могу написать немного упрощенного c кода, чтобы исправить мою непосредственную проблему. Пожалуйста, go легко объясните мне: -)

Пример кода:

using OpenCvSharp;
using OpenCvSharp.Extensions;

namespace Weld_picture
{
    public partial class Form1 : Form
    {
        // Create class-level accessible variables
        int Welding_camera_ID = 1;
        VideoCapture capture;
        Mat frame;
        Bitmap image;
        private Thread camera;
        bool isCameraRunning = false;

        string Serial_command = "";

        Bitmap Stored_image_1;
        Bitmap Stored_image_2;

        bool Image_saved = false;
        string Station_ID = "GWM-PWS-01";
        string File_name = "";

        private void CaptureCamera() // from someone else's sample code
        {
            camera = new Thread(new ThreadStart(CaptureCameraCallback));
            camera.Start();
        }

        private void CaptureCameraCallback() // from someone else's sample code
        {
            frame = new Mat();
            capture = new VideoCapture(Welding_camera_ID);
            capture.Open(Welding_camera_ID);

            if (capture.IsOpened())
            {
                while (isCameraRunning)
                {
                    capture.Read(frame);
                    image = BitmapConverter.ToBitmap(frame);
                    if (pictureBox1.Image != null)
                    {
                        pictureBox1.Image.Dispose();
                    }
                    pictureBox1.Image = image;
                }
            }
        }

        public Form1()
        {
            InitializeComponent();

            SerialPort1.Open();
        }

        private void SerialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            string dummy;
            char CR = (char)0x0D;

            while (SerialPort1.BytesToRead > 0)
            {
                Serial_command += (char)SerialPort1.ReadByte();
            }

            while (Serial_command.IndexOf(CR) > 0)
            {
                dummy = Serial_command.Substring(0, Serial_command.IndexOf(CR));
                Serial_command = Serial_command.Substring(Serial_command.IndexOf(CR) + 1, (Serial_command.Length - (Serial_command.IndexOf(CR) + 1)));

                Serial_command.Trim();
                dummy.Trim();

                proc_Process_serial_data(dummy); 
            }
        }

        //*************************************************************************************************************************************
        /* the first timer is a 5-second interval. It's the "memory" function so that if/when the save-to-disk is triggered I can store the last-time-shutter-open image */
        //*************************************************************************************************************************************

        private void Timer_picture_interval_Tick(object sender, EventArgs e)
        {
            checkBox1.Checked = !checkBox1.Checked;

            Timer_picture_interval.Stop();
            Stored_image_2 = Stored_image_1;
            Stored_image_1 = (Bitmap) pictureBox1.Image;
            Timer_picture_interval.Start();
        }

        //*************************************************************************************************************************************
        // the second timer is a 30-second interval. It's the way to turn capture off if the PLC/camera box somehow goes off-line 
        //*************************************************************************************************************************************

        private void Timer_camera_powerdown_Tick(object sender, EventArgs e)
        {
            if (isCameraRunning)
                capture.Release();
            isCameraRunning = false;
            Timer_picture_interval.Stop();
        }

        //*************************************************************************************************************************************

        private void proc_Process_serial_data(string Serial_string)
        {
            if (Serial_string.IndexOf("Still here") > 0)
            {
                if (!isCameraRunning)
                    CaptureCamera();
                isCameraRunning = true;
            }

            if (Serial_string.IndexOf("Sun's up") > 0)
            {
                Timer_picture_interval.Start();
                Timer_camera_powerdown.Start();
            }

            if (Serial_string.IndexOf("It's dark") > 0)
            {
                if ((Stored_image_2 != null) && (!Image_saved)) // in case there's 2 subsequent requests to save the same thing (weld stutter)
                {
                    File_name = "C:\\Users\\GreenWorld\\Desktop\\" + Station_ID + " D" + DateTime.Now.ToString("yyyy_MM_dd THH_mm_ss") + ".jpg";
                    Stored_image_2.Image.Save("C:\\Users\\GreenWorld\\Desktop\\test.bmp" , System.Drawing.Imaging.ImageFormat.Bmp );

                    Image_saved = true;
                    Timer_picture_interval.Stop();
                }
                Timer_camera_powerdown.Start();
            }
        }
    }
}

1 Ответ

0 голосов
/ 10 июля 2020

Вероятно, вы сможете исправить ошибку перекрестной передачи, просто вызвав свой метод proc_Process_serial_data() в вызове Invoke().

Изменить:

proc_Process_serial_data(dummy);

To:

this.Invoke((MethodInvoker)delegate ()
{
    proc_Process_serial_data(dummy);
});     

Кроме того, эти две строки на самом деле ничего не делают:

Serial_command.Trim();
dummy.Trim();

Для Trim() строк вы захватили возвращенные строки и переназначили их исходным переменным :

Serial_command = Serial_command.Trim();
dummy = dummy.Trim();
       
...