如何将光流场(浮点数)映射到像素数据(字符)以进行图像变形?
Posted
技术标签:
【中文标题】如何将光流场(浮点数)映射到像素数据(字符)以进行图像变形?【英文标题】:How to map optical flow field (float) to pixel data (char) for image warping? 【发布时间】:2011-06-16 07:31:49 【问题描述】:我一直在使用 OpenCV 中的光流函数,但被卡住了。我已经使用 Farneback 方法成功生成了 X 和 Y 光流场/图,但我不知道如何将其应用于输入图像坐标以扭曲图像。生成的 X 和 Y 字段是 32 位浮点类型 (0-1.0),但是这如何转换为输入和输出图像的坐标?比如1.0什么的?图片的宽度?两者的区别?
另外,我不确定我的循环在应用变换/扭曲时会是什么样子。我做了很多循环来改变颜色,但像素总是保持在同一个位置。移动像素对我来说是新领域!
更新:我得到了这个工作,但生成的图像很乱:
//make a float copy of 8 bit grayscale source image
IplImage *src_img = cvCreateImage(img_sz, IPL_DEPTH_32F, 1);
cvConvertScale(input_img,src_img,1/255.0); //convert 8 bit to float
//create destination image
IplImage *dst_img = cvCreateImage(img_sz, IPL_DEPTH_32F, 1);
for(y = 0; y < flow->height; y++)
//grab flow maps for X and Y
float* vx = (float*)(velx->imageData + velx->widthStep*y);
float* vy = (float*)(vely->imageData + vely->widthStep*y);
//coords for source and dest image
const float *srcpx = (const float*)(src_img->imageData+(src_img->widthStep*y));
float *dstpx = (float*)(dst_img->imageData+(dst_img->widthStep*y));
for(x=0; x < flow->width; x++)
int newx = x+(vx[x]);
int newy = (int)(vy[x])*flow->width;
dstpx[newx+newy] = srcpx[x];
我无法让它工作。输出只是乱码:
cvRemap(src_img,dst_img,velx,vely,CV_INTER_CUBIC,cvScalarAll(0));
【问题讨论】:
光流为您提供 X 或 Y 方向上每个像素块的速度 好的,那么从流图返回的浮点值是速度值?是对的吗?该速度值如何应用于像素坐标? 每个块由像素组成,块的每个像素共享块的速度。使用图像的大小和生成的速度矩阵来计算像素块映射 没有“块”,这是一种密集的光流算法,每个像素都有一个速度。 【参考方案1】:流向量是速度值。如果图像 1 中位置(x, y)
的像素具有流向量(vx, vy)
,则估计它位于(x+vx, y+vy)
位置(因此这些值实际上并不在[0, 1]
范围内——它们可以更大,并且是负数)。进行变形的最简单方法是使用这些值创建浮点图像(x 方向为x+vx
,y 方向类似),然后使用cv::remap
。
【讨论】:
好的,我接受了你的建议,现在我已经在 X 轴上工作了!我仍然需要弄清楚如何让 Y 轴更新。以及使用 cvRemap() 的目的是什么? 在 x 和 y 方向上完全相同,没有理由一个应该“工作”而另一个不应该“工作”。和cv::remap
进行翘曲。如果您使用的是 c++,则不应使用 cvRemap
,正如您的标签所说,opencv 具有独特的 c++ 接口。
我更新了上面的帖子以显示我正在使用的代码。我无法让 cvRemap 工作。我使用的是 C 语法,我将 C++ 放在标签中的唯一原因是因为大部分 OpenCV 都是基于 C++ 的(我必须使用 g++ 编译)。
opencv 仅与 C 一起工作得很好——你可以用 gcc 编译东西。如果非得用g++编译,那是别的原因。
对不起,让我澄清一下。问题是如果我设置 Xcode 来编译 C 而不是 C++,我会得到一堆链接器错误(未定义的符号)。【参考方案2】:
使用 OpenCV
https://github.com/opencv/opencv/blob/master/samples/python/opt_flow.py
def warp_flow(img, flow):
h, w = flow.shape[:2]
flow = -flow
flow[:,:,0] += np.arange(w)
flow[:,:,1] += np.arange(h)[:,np.newaxis]
res = cv2.remap(img, flow, None, cv2.INTER_LINEAR)
return res
【讨论】:
以上是关于如何将光流场(浮点数)映射到像素数据(字符)以进行图像变形?的主要内容,如果未能解决你的问题,请参考以下文章
如果以十进制形式收到的值是一个空字符串,我该如何将其转换为浮点数?