Image 如何在opencv中获得真实位置的图像像素?
我想检索图像中像素的rgb。 但位置不是整数位置,而是实值(x,y)。 我想要一个双线性插值。 我该怎么做Image 如何在opencv中获得真实位置的图像像素?,image,opencv,interpolation,Image,Opencv,Interpolation,我想检索图像中像素的rgb。 但位置不是整数位置,而是实值(x,y)。 我想要一个双线性插值。 我该怎么做 非常感谢双线性插值只意味着根据与正在检查的像素最近的4个像素对值进行加权。权重可按如下方式计算 cv::Point2f current_pos; //assuming current_pos is where you are in the image //bilinear interpolation float dx = current_pos.x-(int)current_pos.x;
非常感谢双线性插值只意味着根据与正在检查的像素最近的4个像素对值进行加权。权重可按如下方式计算
cv::Point2f current_pos; //assuming current_pos is where you are in the image
//bilinear interpolation
float dx = current_pos.x-(int)current_pos.x;
float dy = current_pos.y-(int)current_pos.y;
float weight_tl = (1.0 - dx) * (1.0 - dy);
float weight_tr = (dx) * (1.0 - dy);
float weight_bl = (1.0 - dx) * (dy);
float weight_br = (dx) * (dy);
最终值计算为每个像素与其各自权重的乘积之和双线性插值仅意味着根据与正在检查的像素最近的4个像素对值进行加权。权重可按如下方式计算
cv::Point2f current_pos; //assuming current_pos is where you are in the image
//bilinear interpolation
float dx = current_pos.x-(int)current_pos.x;
float dy = current_pos.y-(int)current_pos.y;
float weight_tl = (1.0 - dx) * (1.0 - dy);
float weight_tr = (dx) * (1.0 - dy);
float weight_bl = (1.0 - dx) * (dy);
float weight_br = (dx) * (dy);
您的最终值计算为每个像素与其各自权重的乘积之和子像素访问没有简单的函数,但我可以建议您几个选项:
cv::Vec3b getColorSubpix(const cv::Mat& img, cv::Point2f pt)
{
cv::Mat patch;
cv::getRectSubPix(img, cv::Size(1,1), pt, patch);
return patch.at<cv::Vec3b>(0,0);
}
cv::Vec3b getColorSubpix(常数cv::Mat&img,cv::Point2f pt)
{
cv::垫片;
cv::getRectSubPix(img,cv::Size(1,1),pt,patch);
返回补丁。at(0,0);
}
cv::Vec3b getColorSubpix(const cv::Mat& img, cv::Point2f pt)
{
cv::Mat patch;
cv::remap(img, patch, cv::Mat(1, 1, CV_32FC2, &pt), cv::noArray(),
cv::INTER_LINEAR, cv::BORDER_REFLECT_101);
return patch.at<cv::Vec3b>(0,0);
}
cv::Vec3b getColorSubpix(常数cv::Mat&img,cv::Point2f pt)
{
cv::垫片;
cv::重新映射(img、补丁、cv::Mat(1、1、cv_32FC2和pt)、cv::noArray(),
cv::内部线性,cv::边界反射(101);
返回补丁。at(0,0);
}
cv::Vec3b getColorSubpix(const cv::Mat& img, cv::Point2f pt)
{
assert(!img.empty());
assert(img.channels() == 3);
int x = (int)pt.x;
int y = (int)pt.y;
int x0 = cv::borderInterpolate(x, img.cols, cv::BORDER_REFLECT_101);
int x1 = cv::borderInterpolate(x+1, img.cols, cv::BORDER_REFLECT_101);
int y0 = cv::borderInterpolate(y, img.rows, cv::BORDER_REFLECT_101);
int y1 = cv::borderInterpolate(y+1, img.rows, cv::BORDER_REFLECT_101);
float a = pt.x - (float)x;
float c = pt.y - (float)y;
uchar b = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[0] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[0] * a) * (1.f - c)
+ (img.at<cv::Vec3b>(y1, x0)[0] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[0] * a) * c);
uchar g = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[1] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[1] * a) * (1.f - c)
+ (img.at<cv::Vec3b>(y1, x0)[1] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[1] * a) * c);
uchar r = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[2] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[2] * a) * (1.f - c)
+ (img.at<cv::Vec3b>(y1, x0)[2] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[2] * a) * c);
return cv::Vec3b(b, g, r);
}
cv::Vec3b getColorSubpix(常数cv::Mat&img,cv::Point2f pt)
{
断言(!img.empty());
断言(img.channels()==3);
int x=(int)pt.x;
int y=(int)pt.y;
int x0=cv::borderInterpolate(x,img.cols,cv::BORDER\u REFLECT\u 101);
int x1=cv::borderInterpolate(x+1,img.cols,cv::BORDER\u REFLECT\u 101);
int y0=cv::borderInterpolate(y,img.rows,cv::BORDER\u REFLECT\u 101);
int y1=cv::borderInterpolate(y+1,img.rows,cv::BORDER\u REFLECT\u 101);
浮点数a=pt.x-(浮点数)x;
浮点数c=pt.y-(浮点数)y;
uchar b=(uchar)cvRound((在(y0,x0)[0]*(1.f-a)+在(y0,x1)[0]*a)的img.at)*(1.f-c)
+(在(y1,x0)[0]*(1.f-a)+img.在(y1,x1)[0]*a)*c);
uchar g=(uchar)cvRound((img.at(y0,x0)[1]*(1.f-a)+img.at(y0,x1)[1]*a)*(1.f-c)
+(在(y1,x0)[1]*(1.f-a)+img.at(y1,x1)[1]*a)*c);
uchar r=(uchar)cvRound((img.at(y0,x0)[2]*(1.f-a)+img.at(y0,x1)[2]*a)*(1.f-c)
+(在(y1,x0)[2]*(1.f-a)+img.at(y1,x1)[2]*a)*c);
返回cv::Vec3b(b,g,r);
}
亚像素访问没有简单的功能,但我可以向您推荐几个选项:
cv::Vec3b getColorSubpix(const cv::Mat& img, cv::Point2f pt)
{
cv::Mat patch;
cv::getRectSubPix(img, cv::Size(1,1), pt, patch);
return patch.at<cv::Vec3b>(0,0);
}
cv::Vec3b getColorSubpix(常数cv::Mat&img,cv::Point2f pt)
{
cv::垫片;
cv::getRectSubPix(img,cv::Size(1,1),pt,patch);
返回补丁。at(0,0);
}
cv::Vec3b getColorSubpix(const cv::Mat& img, cv::Point2f pt)
{
cv::Mat patch;
cv::remap(img, patch, cv::Mat(1, 1, CV_32FC2, &pt), cv::noArray(),
cv::INTER_LINEAR, cv::BORDER_REFLECT_101);
return patch.at<cv::Vec3b>(0,0);
}
cv::Vec3b getColorSubpix(常数cv::Mat&img,cv::Point2f pt)
{
cv::垫片;
cv::重新映射(img、补丁、cv::Mat(1、1、cv_32FC2和pt)、cv::noArray(),
cv::内部线性,cv::边界反射(101);
返回补丁。at(0,0);
}
cv::Vec3b getColorSubpix(const cv::Mat& img, cv::Point2f pt)
{
assert(!img.empty());
assert(img.channels() == 3);
int x = (int)pt.x;
int y = (int)pt.y;
int x0 = cv::borderInterpolate(x, img.cols, cv::BORDER_REFLECT_101);
int x1 = cv::borderInterpolate(x+1, img.cols, cv::BORDER_REFLECT_101);
int y0 = cv::borderInterpolate(y, img.rows, cv::BORDER_REFLECT_101);
int y1 = cv::borderInterpolate(y+1, img.rows, cv::BORDER_REFLECT_101);
float a = pt.x - (float)x;
float c = pt.y - (float)y;
uchar b = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[0] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[0] * a) * (1.f - c)
+ (img.at<cv::Vec3b>(y1, x0)[0] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[0] * a) * c);
uchar g = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[1] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[1] * a) * (1.f - c)
+ (img.at<cv::Vec3b>(y1, x0)[1] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[1] * a) * c);
uchar r = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[2] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[2] * a) * (1.f - c)
+ (img.at<cv::Vec3b>(y1, x0)[2] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[2] * a) * c);
return cv::Vec3b(b, g, r);
}
cv::Vec3b getColorSubpix(常数cv::Mat&img,cv::Point2f pt)
{
断言(!img.empty());
断言(img.channels()==3);
int x=(int)pt.x;
int y=(int)pt.y;
int x0=cv::borderInterpolate(x,img.cols,cv::BORDER\u REFLECT\u 101);
int x1=cv::borderInterpolate(x+1,img.cols,cv::BORDER\u REFLECT\u 101);
int y0=cv::borderInterpolate(y,img.rows,cv::BORDER\u REFLECT\u 101);
int y1=cv::borderInterpolate(y+1,img.rows,cv::BORDER\u REFLECT\u 101);
浮点数a=pt.x-(浮点数)x;
浮点数c=pt.y-(浮点数)y;
uchar b=(uchar)cvRound((在(y0,x0)[0]*(1.f-a)+在(y0,x1)[0]*a)的img.at)*(1.f-c)
+(在(y1,x0)[0]*(1.f-a)+img.在(y1,x1)[0]*a)*c);
uchar g=(uchar)cvRound((img.at(y0,x0)[1]*(1.f-a)+img.at(y0,x1)[1]*a)*(1.f-c)
+(在(y1,x0)[1]*(1.f-a)+img.at(y1,x1)[1]*a)*c);
uchar r=(uchar)cvRound((img.at(y0,x0)[2]*(1.f-a)+img.at(y0,x1)[2]*a)*(1.f-c)
+(在(y1,x0)[2]*(1.f-a)+img.at(y1,x1)[2]*a)*c);
返回cv::Vec3b(b,g,r);
}
如果希望重复或一致地执行此操作,则使用映射可以更有效。另一个优点是选择插值方法以及如何处理边界条件。最后在GPU上实现了部分插值函数。
如果您希望重复或一致地执行此操作,则使用映射可以更有效。另一个优点是选择插值方法以及如何处理边界条件。最后在GPU上实现了部分插值函数。
不幸的是,我没有足够的分数将此作为对已接受答案的评论。。。我对代码进行了调整,以适应我自己的问题,这需要在单个浮动通道矩阵上进行插值 我想我需要一些直觉,哪种方法是最快的 我实现了Andrey Kamaev答案中的3种方法以及一个简单的最近邻(基本上只是四舍五入坐标) 我用一个矩阵a(100x100)做了一个实验,我刚刚把它装满了垃圾。然后我制作了一个矩阵B(400x400),其中填充了从a插值的值,使得:B(I,j)=a(I/4,j/4) 每次运行1000次,以下是平均运行次数:
- 最近邻点:2.173毫秒
- getRectSubPix:26.506毫秒
- 重新映射:114.265毫秒
- 手动:5.086毫秒
- 手动无边框内插:3.842毫秒