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

opencv:单像素赋值混乱 我最近在用OpenCV和C++进行一个项目,我发现了一个奇怪的事情: 当我尝试访问IplImage中的单个像素值并分配其他值时,它可以正常运行,但结果是它只能操作整个图像的一部分,c++,opencv,C++,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* p

相关代码:

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];
        }
  }
}
为什么代码的第一部分不起作用是有道理的。但是我仍然不知道为什么代码的第二部分不起作用。 我现在有我的全部代码更新在这里,希望你能帮助我使这一权利。非常感谢你的帮助

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);
}
CvCapture*video_gray=cvCreateFileCapture(“test_gray.avi”);
const double fps=cvGetCaptureProperty(视频为灰色,CV为CAP为属性fps);
const int width=(int)cvGetCaptureProperty(视频\u灰度、CV\u CAP\u属性\u帧宽度);
const int height=(int)cvGetCaptureProperty(视频灰、CV帽、道具、帧高);
常数CvSize size=CvSize(宽度、高度);
IplImage*当前_帧=cvCreateImage(大小,IPL_深度_8U,1);
IplImage*output_frame=cvCreateImage(大小,IPL_深度,1);
int标志=0;
CVD(“试验”,1);
cvNamedWindow(“测试2”,1);
而((当前_帧=cvQueryFrame(视频_灰))!=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];
    }
  }
}
IplImage*output\u frame=cvCreateImage(大小,IPL\u深度,1);
IplImage*当前_帧=cvCreateImage(大小,IPL_深度_8U,1);
而((当前_帧=cvQueryFrame(视频_灰))!=0)
{
对于(int row=0;rowimageData+当前_帧->宽度步长*行);
uchar*ptr_输出_帧=(uchar*)(输出_帧->图像数据+输出_帧->宽度步长*行);
for(int cols=0;colsnChannels];
}
}
}
<>但是你应该尝试切换到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);
}
cv::VideoCapture video=cv::VideoCapture(“test_gray.avi”);
整型宽度=。。。
整数高度=。。。
cv::拍摄的Mat图像;
cv::Mat image_gray;//如果需要
cv::Mat图像\ U输出1=cv::Mat(高度、宽度、cv\ U 8UC1);
cv::Mat图像输出2=cv::Mat(高度、宽度、cv_8UC1);
while(video.read(图像捕获))
{
//如果要将图像转换为
如果(图像捕获.channels()>1)
{
cv::CVT颜色(图像捕获、图像灰度、cv灰度);
}
其他的
{
图像\灰度=捕获的图像\灰度;
}
[...]

对于(int j=0;如果您使用C++,则请不要使用iPLIMAGE,而是使用CV::MAT图像。初始化代码< <代码>大小>代码>什么是什么?<代码> CurrnGyFrase>宽度> /Cord>和<代码> CurrngFrask>高度< /COD>每次迭代?谢谢,是的,我已经尝试将IPLIGION转换到MAT,并使用CurrnEngFrimeMat.Matt。(row,cols)赋值。但是结果保持不变,我无法复制整个图像。至于大小,我的初始值是:CvCapture*video\u gray=cvCreateFileCapture(“test\u gray.avi”);const int width=(int)cvGetCaptureProperty(video\u gray,CV\u CAP\u PROP\u FRAME\u width);const int height=(int)cvGetCaptureProperty(视频为灰色,CV为帽状,道具为框架高度);常量CvSize size=CvSize(宽度、高度);当前帧->宽度和当前帧->高度在每次迭代中都不会更改。您是否验证了它们在每次迭代中都不会更改?GetProperty并不总是正确的。并且您应该在开始时忽略IplImage。使用cv::VideoCapture。再次感谢!我已经仔细验证了当前帧->宽度和当前帧->h八个在每次迭代中都不会改变。它们与应该的方式完全相同。另外,output_frame->width和output_frame->height是正确的。但是,我发现一些奇怪的事情:在我的例子中,current_frame->widthStep=1920,output_frame->widthStep=640。我发现在初始化IplImage:IplImage*current_frame=cvCreateImage之后(大小,IPL_深度_8U,1);宽度步长为640,执行当前_帧后=cvQueryFrame(视频_灰色),它变成了1920年。非常感谢!它很有效!事实上我仍然不知道原因。我在节目中读到的视频确实是灰色的,虽然它是由我的代码转换成灰色的视频。我是Opencv的新手,我很幸运你能帮我做这件事。再次感谢!灰色不需要单通道…3通道灰色[122122]可以描述为单通道[122]值,但不必是…通常,如果您不能/无法分辨不同的内容,则OpenCV提供的输入图像始终是3通道图像。例如,cv::imread有一个标志,可以始终作为灰度加载(可能带有转换)或者以原始文件中的方式加载图像。如果不设置标志,则始终为3通道图像,即使它们显示灰色。可能是cv::VideoCapture(和C等效)有不同的标志/属性,我不确定。明白了。从你那里学到了很多。你能推荐一些书来学习opencv吗?我在攻读博士期间可能仍然经常使用它。现在我正在使用Learning opencv,我觉得它有点太旧了。哈哈。它应该能够轻松地将每个IplImage代码版本转换为cv::Mat版本。通常您只需将函数语法从cvBLABLA更改为cv::BLABLA,并查看OpenCV文档如何选择参数。不幸的是,我不知道任何好书(尽管可能有),但internet上充满了不错的教程、代码示例和stackOverflow问题=)老实说,这是我第一次使用stackoverflow。太棒了。很高兴认识你!
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];
    }
  }
}
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);
}