2015-05-15 3 views
-1

Я недавно работал с OpenCV и C++ для проекта, и я обнаружил странную вещь: , когда я пытаюсь получить доступ к одному пиксельному значению в IplImage и назначить другое значение, он может работать правильно, но результат заключается в том, что он может работать только частью всего изображения.opencv: одиночная ошибка смещения пикселей

соответствующий код:

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

Я обнаружил, что output_frame-> widthStep отличается от current-> widthStep после current_frame выполняется в следующем коде:

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); 
} 
+0

Если вы используете C++, тогда, пожалуйста, не используйте IplImage, но cv :: Mat image. – Micka

+0

Как инициализируется 'размер'? Что такое 'height' и какое значение' current_frame-> width' и 'current_frame-> height' на каждой итерации? – Micka

+0

Спасибо. Да, я попытался перенести IplImage на Mat и использовать current_frame_mat.at (строка, cols), чтобы присвоить значение. Но результат остается тем же, и я не могу скопировать весь образ. Что касается размера, я инициализировал его следующим образом: CvCapture * video_gray = cvCreateFileCapture ("test_gray.avi"); const int width = (int) cvGetCaptureProperty (video_gray, CV_CAP_PROP_FRAME_WIDTH); \t const int height = (int) cvGetCaptureProperty (video_gray, CV_CAP_PROP_FRAME_HEIGHT); const CvSize size = cvSize (ширина, высота); Высота current_frame-> width и current_frame-> не изменяется на каждой итерации. – marvelous

ответ

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]; 
    } 
    } 
} 

но вы действительно должны попытаться переключиться на API C++: попробовать что-то вроде этого:

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); 
} 

гораздо проще в использовании, и вы все равно можете сделать его более эффективным с помощью указателей строк на каждой итерации и т. Д.

+0

Большое спасибо! Оно работает! На самом деле я по-прежнему не причина. Видео, которое я прочитал в программе, действительно серое, хотя оно преобразуется в серое видео по моим кодам. Я новичок в Opencv, и мне очень повезло, что вы помогли мне с этим. Еще раз спасибо! – marvelous

+0

серый цвет не обязательно должен быть одноканальным ... 3-канальный серый цвет [122,122,122] может быть описан как одноканальное значение [122], но не обязательно ... обычно входные изображения, предоставляемые OpenCV, всегда равны 3 канальные изображения, если вы не можете/не можете сказать что-то другое. например cv :: imread имеет флаг либо всегда загружать как оттенки серого (возможно, с преобразованием), либо загружать изображение так, как оно есть в исходном файле. Если вы не устанавливаете флаги, всегда будут 3-канальные изображения, даже если они показывают серые цвета. Возможно, cv :: VideoCapture (и C-эквивалент) имеют разные флаги/свойства, я не уверен. – Micka

+0

Получите это. Многому научился у вас. Можно ли рекомендовать некоторые книги для изучения opencv? Я все еще могу использовать его во время моего исследования Phd. Сейчас я использую Learning Opencv, и я думаю, что он слишком стар. ЛОЛ. – marvelous

Смежные вопросы