OpenCV中的采样函数cvInitLineIterator()和CV_NEXT_LINE_POINT(),可以很容易对任意直线上的像素进行采样。
CVAPI(int) cvInitLineIterator(const CvArr* image,CvPoint pt1, CvPoint pt2,
CvLineIterator* line_iterator,
int connectivityCV_DEFAULT(8),
int left_to_rightCV_DEFAULT(0));
输入参数image可以是任意数据类型和任何通道数
点pt1和pt2是线段的两个端点。
迭代器line_iterator说明直线上两个像素之间的移动步长。
如果图像是多通道的,每次调用CV_NEXT_LINE_POINT()函数都使line_iterator指向下一个像素。
每个通道的像素值可同时用line_iterator.ptr[0],line_iterator.ptr[1],line_iterator.ptr[2]依次得到。
下面看一个具体应用:
从一个视频文件中读取所有像素的GRB值,收集这些数值并将其分成三个文件。
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
using namespace std;
using namespace cv;
#define CVX_RED CV_RGB(0xff, 0x00, 0x00)
#define CVX_GREEN CV_RGB(0x00, 0xff, 0x00)
#define CVX_BLUE CV_RGB(0x00, 0x00, 0xff)
int main()
{
/*1、载入一个视频*/
const char videoname[] = "/Users/linwang/LinMovie/Wolf.mp4";
//通过参数设置要读取的文件,返回一个指向capture的结构指针
CvCapture * capture = cvCreateFileCapture(videoname);
/*2、设置相关变量*/
int max_buffer = 0; //返回直线上迭代的点的个数
IplImage * rawIamge;
CvLineIterator iterator; //迭代器
/*3、准备写入文件*/
FILE * ftprb = fopen("blines.csv","w");
FILE * ftprg = fopen("glines.csv","w");
FILE * ftprr = fopen("rlines.csv","w");
CvPoint pt1 , pt2;
for(;;)
{
//从摄像头或视频抓去帧
if(!cvGrabFrame(capture))
{
break;
}
//取回由函数抓取的图像
rawIamge = cvRetrieveFrame(capture);
//返回线上迭代的点的个数
max_buffer = cvInitLineIterator(rawIamge, pt1, pt2, &iterator);
for(int j = 0;j<max_buffer;j++)
{
fprintf(ftprb, "%d,",iterator.ptr[0]);
fprintf(ftprg, "%d,",iterator.ptr[1]);
fprintf(ftprr, "%d,",iterator.ptr[2]);
iterator.ptr[2] = 255; //red做一个标记
CV_NEXT_LINE_POINT(iterator); //迭代到写一个像素
}
fprintf(ftprb, "/n");
fprintf(ftprg, "/n");
fprintf(ftprr, "/n");
}
fclose(ftprb);
fclose(ftprg);
fclose(ftprr);
cvReleaseCapture(&capture);
}