0

I want to extract the data from a frame of opencv matrix in 420 video format. 420 Format means read the first channel as it is i.e. full first channel. For the second and third channel in frame read in such a way that read alternate rows and columns i.e. for the second channel we will read pixel (0,0) then (0,2) then (0,4) ....... (2,0) then (2,2) and so on ...

I have written the code but I am getting reading and writing violation are random. I am not able to figure out why

array size is rows x cols x 1.5 ...... 1.5 because for the second and third channel size is reduced to quarter.

Code is

    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 = *(&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);
                        }
                    }
                }
            }
        }
    }

4
  • 1
    You have a typo here int c = 0; r < frame.cols; c+=2. Also, you should cast ch to int, or short if you want to see integer value in range (0,255) instead of characters encoded by this ASCII code. Commented Oct 27, 2020 at 6:15
  • Yes that was typo but it is not going in the second channel. It is giving read violation error in the first channel at random location Commented Oct 27, 2020 at 6:17
  • 1
    This uchar * arr = new uchar(arraySize); allocates one byte, you want to create array, so it should be: uchar * arr = new uchar[arraySize];, now you read out of bounds here arr[arrInd++] = chr;. Commented Oct 27, 2020 at 6:19
  • 1
    @rafix07 Thanks a lot. This was foolish mistake by me. Please write this as answer so that I can accept the answer as well as upvote it. Commented Oct 27, 2020 at 6:24

1 Answer 1

1

Crash is caused by reading out of bounds

arr[arrInd++] = chr;

because by the line

uchar * arr = new uchar(arraySize);

you allocate only one byte. It should be: uchar * arr = new uchar[arraySize]; - the way of creating dynamic array.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.