преобразование данных из матрицы в массив из фрейма матрицы opencv

#c #arrays #image #opencv #matrix

#c #массивы #изображение #opencv #матрица

Вопрос:

Я хочу извлечь данные из кадра матрицы opencv в формате видео 420. Формат 420 означает чтение первого канала таким, какой он есть, т.Е. Полный первый канал. Для второго и третьего канала в кадре считывается таким образом, чтобы считывать альтернативные строки и столбцы, т.Е. Для второго канала мы будем считывать пиксель (0,0), затем (0,2), затем (0,4) ……. (2,0) затем (2,2) и так далее…

Я написал код, но я получаю случайные нарушения чтения и записи. Я не могу понять, почему

размер массива равен строкам x cols x 1.5 …… 1.5, потому что для второго и третьего канала размер уменьшается до четверти.

Код

     VideoCapture cap(readFile);
    if (!cap.isOpened()) {
            
            cout << "Error opening video stream or file" << endl;
            
            return -1;
            
    }
    
    int arraySize = 640 * 824 * 1.5;
    uchar * arr = new uchar(arraySize);
    int frame_width = cap.get(CAP_PROP_FRAME_WIDTH);
    int frame_height = cap.get(CAP_PROP_FRAME_HEIGHT);
    int fps = cap.get(CAP_PROP_FPS);
    Size S = Size(frame_width, frame_height); // Declare Size structure
    int fourcc = VideoWriter::fourcc('H', '2', '6', '5');
    //int fourcc = VideoWriter::fourcc(*"hvc1");
    outputVideo.open(saveFile, fourcc, fps, S);
    while (1)
    {
        Mat framergb;
        Mat frame = framergb.clone();
        cap >> framergb;

        
        cvtColor(framergb, frame, 83);
        std::cout << "Channels = " << frame.channels() << endl;



        std::vector<uchar> array(framergb.rows*framergb.cols*framergb.channels());

        
        if (type == "420")
        {
            Mat rgbchannel[3];
            cv::split(frame, rgbchannel);
            //arr = new uchar(int(frame.rows*frame.cols*1.5));
//          int size = *(amp;arr   1) - arr;
            cout << "Array Size = " << sizeof(arr);// << " and " << size << endl;
            int arrInd = 0;
            uchar chr = 0;
            for (int ch = 0; ch < 3; ch  )
            {
                if (ch == 0)
                {
                    for (int r = 0; r < frame.rows; r  )
                    {
                        for (int c = 0; c < frame.cols; c  )
                        {
                            chr  = rgbchannel[ch].at<uchar>(r, c);
                            arr[arrInd  ] = chr;
                            cout << "cg = " << ch << ", r = " << r << ", c= " << c <<"ch = " << chr<< endl;
                            //if (c == 638)
                                //cout << "Stop";
                        }
                        //cout << "cg = " << ch << ", r = " << r <<endl;
                    }
                    cout << "cg = " << ch << endl;
                }                       
                else
                {
                    for (int r = 0; r < frame.rows; r =2)
                    {
                        for (int c = 0; r < frame.cols; c =2)
                        {
                            arr[arrInd  ] = rgbchannel[ch].at<uchar>(r, c);
                        }
                    }
                }
            }
        }
    }

  

Комментарии:

1. Здесь у вас опечатка int c = 0; r < frame.cols; c =2 . Кроме того, вы должны преобразовать ch в int или short, если хотите увидеть целочисленное значение в диапазоне (0,255) вместо символов, закодированных этим ASCII-кодом.

2. Да, это была опечатка, но она не передается по второму каналу. Это выдает ошибку нарушения чтения в первом канале в случайном месте

3. Это uchar * arr = new uchar(arraySize); выделяет один байт, вы хотите создать массив, поэтому он должен быть: uchar * arr = new uchar[arraySize]; , теперь вы читаете здесь out of bounds arr[arrInd ] = chr; .

4. @rafix07 Большое спасибо. Это была моя глупая ошибка. Пожалуйста, напишите это как ответ, чтобы я мог принять ответ, а также проголосовать за него.

Ответ №1:

Сбой вызван чтением за пределы

 arr[arrInd  ] = chr;
  

потому что по строке

 uchar * arr = new uchar(arraySize);
  

вы выделяете только один байт. Это должно быть: uchar * arr = new uchar[arraySize]; — способ создания динамического массива.