opencv:单个像素分配混淆

时间:2015-05-15 14:11:22

标签: c++ opencv

我最近在一个项目中使用OpenCV和C ++,我发现了一个奇怪的事情: 当我尝试在IplImage中访问单个像素值并分配其他值时,它可以正常运行,但结果是它只能操作整个图像的一部分。

相关代码:

IplImage* output_frame = cvCreateImage(size, IPL_DEPTH_8U, 1);
IplImage* current_frame = cvCreateImage(size, IPL_DEPTH_8U, 1);
while((current_frame = cvQueryFrame(video_gray)) != 0 )
{
  for (int row=0;row<height;row++)
  {

        uchar* ptr_current_frame = (uchar *)(current_frame->imageData+current_frame->widthStep*row);
        uchar* ptr_output_frame = (uchar *)(output_frame->imageData+output_frame->widthStep*row);
        for (int cols=0;cols<width;cols++)
        {
            //other codes...
            ptr_output_frame[cols]=ptr_current_frame[cols];
        }
  }
}

结果是图像的左侧部分被复制到output_frame。当我运行以下代码时:

IplImage* output_frame = cvCreateImage(size, IPL_DEPTH_8U, 1);
IplImage* current_frame = cvCreateImage(size, IPL_DEPTH_8U, 1);
while((current_frame = cvQueryFrame(video_gray)) != 0 )
{
  for (int row=0;row<height;row++)
  {

        uchar* ptr_current_frame = (uchar *)current_frame->imageData+current_frame->width*row;
        uchar* ptr_output_frame = (uchar *)output_frame->imageData+output_frame->width*row;
        for (int cols=0;cols<width;cols++)
        {
            //other codes...
            ptr_output_frame[cols]=ptr_current_frame[cols];
        }
  }
}

我在output_frame中获得了图像的上部部分。

无论如何,我都无法在output_frame中获取整个图像副本。有人可以帮帮我吗?非常感谢!

[更新] 05/16/2015

我发现在以下代码中执行current_frame之后,output_frame-&gt; widthStep与current-&gt; widthStep不同:

 current_frame = cvQueryFrame(video_gray);

为什么代码的第一部分不起作用是有道理的。但我仍然不知道为什么代码的第二部分不起作用。 我现在更新了我的全部代码,希望你能帮助我做到这一点。我非常感谢你的帮助。

CvCapture* video_gray = cvCreateFileCapture("test_gray.avi");
const double fps = cvGetCaptureProperty(video_gray, CV_CAP_PROP_FPS); 
const int width = (int)cvGetCaptureProperty(video_gray, CV_CAP_PROP_FRAME_WIDTH);
const int height = (int)cvGetCaptureProperty(video_gray, CV_CAP_PROP_FRAME_HEIGHT);
const CvSize size = cvSize(width, height);
IplImage* current_frame = cvCreateImage(size, IPL_DEPTH_8U, 1);
IplImage* output_frame=cvCreateImage(size, IPL_DEPTH_8U, 1);
int flag = 0;
cvNamedWindow("test",1);
cvNamedWindow("test2",1);
while((current_frame = cvQueryFrame(video_gray)) != 0 )
{
    cout<<flag++<<endl;
    if(flag<500) continue;
    for (int row=0;row<height;row++)
    {
        uchar* ptr_current_frame = (uchar *)(current_frame->imageData+current_frame->widthStep*row);
        uchar* ptr_output_frame = (uchar *)(output_frame->imageData+output_frame->widthStep*row);
        for (int cols=0;cols<width;cols++)
        {
            ptr_output_frame[cols]= ptr_current_frame[cols];
        }
    }
    cvShowImage("test",output_frame);
    cvShowImage("test2",current_frame);
    cvWaitKey(10);
}

1 个答案:

答案 0 :(得分:0)

您无法处理频道数量......

请尝试

IplImage* output_frame = cvCreateImage(size, IPL_DEPTH_8U, 1);
IplImage* current_frame = cvCreateImage(size, IPL_DEPTH_8U, 1);
while((current_frame = cvQueryFrame(video_gray)) != 0 )
{
  for (int row=0;row<height;row++)
  {

    uchar* ptr_current_frame = (uchar *)(current_frame->imageData+current_frame->widthStep*row);
    uchar* ptr_output_frame = (uchar *)(output_frame->imageData+output_frame->widthStep*row);
    for (int cols=0;cols<width;cols++)
    {
        //other codes...
        // here insead take care of the channels too. Only write ne channel to the output
        ptr_output_frame[cols]=ptr_current_frame[cols*current_frame->nChannels];
    }
  }
}

但您应该尝试切换到C ++ API:尝试这样的事情:

cv::VideoCapture video = cv::VideoCapture("test_gray.avi");

int width = ...
int height = ...

cv::Mat image_captured;
cv::Mat image_gray; // if wanted
cv::Mat image_output1 = cv::Mat(height, width, CV_8UC1);
cv::Mat image_output2 = cv::Mat(height, width, CV_8UC1);

while(video.read(image_captured))
{
    // if you want to convert the image to 
    if(image_captured.channels() > 1)
    {
        cv::cvtColor(image_captured, image_gray, CV_BGR2GRAY);
    }
    else
    {
        image_gray = image_captured;
    }

    [...]
    for(int j=0; j<height; ++j)
    {
        for(int i=0; i<width; ++i)
        {
            image_output1.at<uchar>(j,i) = image_gray.at<uchar>(j,i); // read from single channel image
            image_output1.at<uchar>(j,i) = image_captured.at<cv::Vec3b>(j,i)[0]; // only read the first channel of a multi-channel image
        }
    }        

}

    cv::imshow("output1", image_output1);
    cv::imshow("output2", image_output2);
    cv::imshow("input", image_capured);

    cv::waitKey(0);
}

更容易使用,你仍然可以通过在每次迭代中使用行指针来提高效率