Разделить кадр изображения на 8*8 для DCT с использованием OpenCV и C++

Мне нужно передать полный путь в метод FrameTo8by8(). В FrameTo8by8() каждый кадр будет разделен на 8*8 блоков. (Например, разрешение моего видео 1280 * 720 = 921 600. После этого 921 600 / 64 (8 * 8) = 14 400. Таким образом, всего будет 14 400 блоков 8 * 8).

VideoSplitEngine.h

class VideoSplitEngine
{
    public:

    static VideoCapture capture;
    static Mat fullimage;

    //Default constructor
    VideoSplitEngine();

    //Declare a virtual destructor:
    virtual ~VideoSplitEngine();

    //Method
    Mat Start();    
    void FrameTo8by8() const; 
    string GetFilePath() const;

    private:
};

VideoSplitEngine.cpp

#include "StdAfx.h"
#include "VideoSplitEngine.h"
#include "UserInfo.h"
#include "Common.h"

VideoCapture VideoSplitEngine::capture;

Mat VideoSplitEngine::fullimage;

Mat VideoSplitEngine::Start()

string VideoSplitEngine::GetFilePath() const
{
  cout<< endl;
  cout << "Place video in Desktop and enter file name (e.g. vid.avi):" << endl;
  cout<<"----------------------------------------------------------"<< endl;

  //Get user desktop file path
  string fullPath;
  string userProfile = getenv("userprofile");   //GetEnvironmentVariable() is to get current userprofile (e.g."C:\Users\L30807")
  string path = userProfile + "\\Desktop\\";
  string vid;

  getline (cin, vid);       //Prompt to input file name
  fullPath = path + vid;
  capture.open(fullPath); //Read video
  cout<< endl;

  return fullPath;
}

Mat VideoSplitEngine::Start()
{
  while(1)
  {
    bool bSuccess = capture.read(fullimage); // read a new frame from video

    if (!bSuccess) //if not success, break loop
    {
        cout << "End of video" << endl;
        destroyWindow("Original Video");
        break;
    }

    imshow("Original Video", fullimage); //show the frame in "Original Video" window

    if(waitKey(30) == 27) //wait for 'esc' key press for 30 ms. If 'esc' key is pressed, break loop
    {
        cout << "esc key is pressed by user" << endl; 
        break; 
    }
  }

return fullimage;
}

void VideoSplitEngine::FrameTo8by8() const
{
    namedWindow("Original", CV_WINDOW_AUTOSIZE); 
    imshow("Original", fullimage); 

    int width = fullimage.size().width; 
    int height = fullimage.size().width; 

    cout << "Original image Width x Height is " << width << "x" << height << endl; 

    // Leave original alone, work on a copy 
    Mat dctImage = fullimage.clone();

    // Step through the copied image with rectangles size 8x8 
    // For each block, split into planes, do dct, and merge back 
    // into the block. (This will affect the image from 
    // which the block is selected each time.) 

    for (int i = 0; i < height; i += 8) 
    { 
        for (int j = 0; j < width; j+= 8) 
        {
            Mat block = dctImage(Rect(i, j, 8, 8));
            vector<Mat> planes; 
            split(block, planes);
            vector<Mat> outplanes(planes.size());

            for (size_t k = 0; k < planes.size(); k++)
            {
                planes[k].convertTo(planes[k], CV_32FC1); 
                dct(planes[k], outplanes[k]);
                outplanes[k].convertTo(outplanes[k], CV_8UC1);
            }
                merge(outplanes, block); 
        } 
    } 

    namedWindow("dctBlockImage"); 
    imshow("dctBlockImage", dctImage);

    waitKey(30); 
}

Мне нужна помощь в том, как разделить его или есть другие способы сделать это?


person user3743939    schedule 08.07.2014    source источник
comment
выглядит немного неуклюже, но по крайней мере должно работать. Вам действительно нужен объединенный DCT из 3 цветовых каналов? или, скорее, сделать его в оттенках серого в начале и работать только на 1 плоскости?   -  person berak    schedule 08.07.2014
comment
Я не могу заставить его работать. Мне нужно объединить dct из 3 цветовых каналов RGB.   -  person user3743939    schedule 08.07.2014
comment
в порядке. так что не так? и, пожалуйста, сделайте это: dctImage(Rect(j, i, 8, 8));   -  person berak    schedule 08.07.2014
comment
эта ошибка вышла Необработанное исключение по адресу 0x767ec42d в VideoWM.exe: исключение Microsoft C++: cv::Exception в ячейке памяти 0x0031e6cc..   -  person user3743939    schedule 08.07.2014
comment
Хорошо удалось решить проблему. Спасибо еще раз.   -  person user3743939    schedule 09.07.2014
comment
@user3743939 user3743939 Если вам удалось решить свою проблему, опубликуйте ее как ответ, чтобы помочь другим людям, которые наткнулись на этот вопрос.   -  person mgttlinger    schedule 18.11.2014


Ответы (1)


1. @berak прав. Прототипом функции Rect() является Rect(x,y,width,height). Таким образом, «j», относящийся к «ширине», должен быть «x». (На самом деле я не нашел прототип Rect() из http://docs.opencv.org/2.4/index.html , но cvRect() в C API — это cvRect(x,y,width,height). Я думаю, что их прототипы могут быть одинаковыми.)

2.for (int i = 0; i < height; i += 8) и for (int j = 0; j < width; j+= 8) вызовут ошибку ""Необработанное исключение в...". Если изменить их на for (int i = 0; i < (height/8)*8; i += 8)иfor (int j = 0; j < (width/8)*8; j+= 8), эта ошибка будет устранена.

3.@user3743939 Если вам удалось решить вашу проблему, опубликуйте свое решение, чтобы помочь другим.

С Уважением

person bknieven    schedule 28.07.2016