我最近在一个项目中使用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);
}
答案 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);
}
更容易使用,你仍然可以通过在每次迭代中使用行指针来提高效率