点击上方“小白学视觉”,选择加"星标"或“置顶”
重磅干货,第一时间送达
彩色图像高斯反向投影
图像反向投影的最终目的是获取ROI然后实现对ROI区域的标注、识别、测量等图像处理与分析,是计算机视觉与人工智能的常见方法之一。图像反向投影通常是彩色图像投影效果会比灰度图像效果要好,原因在于彩色图像带有更多对象细节信息,在反向投影的时候更加容易判断、而转为灰度图像会导致这些细节信息丢失、从而导致分割失败。最常见的是基于图像直方图特征的反向投影。我们这里介绍一种跟直方图反向投影不一样的彩色图像反向投影方法,通过基于高斯的概率分布公式(PDF)估算,反向投影得到对象区域,该方法也可以看做最简单的图像分割方法。缺点是对象颜色光照改变和尺度改变不具备不变性特征。所以需要在光照度稳定情况下成像采集图像数据。在这种情况下使用的高斯概率密度公式为:
输入模型M,对M的每个像素点(R,G,B)计算I=R+G+B r=R/I, g=G/I, b=B/I
根据得到权重比例值,计算得到对应的均值 与标准方差
对输入图像的每个像素点计算根据高斯公式计算P(r)与P(g)的乘积
归一化之后输出结果,即为最终基于高斯PDF的反向投影图像
首先加载模型图像与测试图像
根据模型图像计算得到每个通道对应的均值与标准方差参数
根据参数方差计算每个像素点的PDF值
归一化概率分布图像-即为反向投影图像,显示
根据Mask得到最终颜色模型对象分割
#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
usingnamespace cv;
usingnamespace std;
int main(int argc, char** argv) {
// 加载模型图像与测试图像
Mat src = imread("D:/gloomyfish/gc_test.png");
Mat model = imread("D:/gloomyfish/gm.png");
if(src.empty() || model.empty()) {
printf("could not load image...\n");
return-1;
}
imshow("input image", src);
// 对每个通道 计算高斯PDF的参数
// 有一个通道不计算,是因为它可以通过1-r-g得到
// 无需再计算
Mat R = Mat::zeros(model.size(), CV_32FC1);
Mat G = Mat::zeros(model.size(), CV_32FC1);
int r = 0, g = 0, b = 0;
float sum = 0;
for(int row = 0; row < model.rows; row++) {
uchar* current = model.ptr<uchar>(row);
for(int col = 0; col < model.cols; col++) {
b = *current++;
g = *current++;
r = *current++;
sum = b + g + r;
R.at<float>(row, col) = r / sum;
G.at<float>(row, col) = g / sum;
}
}
// 计算均值与标准方差
Mat mean, stddev;
double mr, devr;
double mg, devg;
meanStdDev(R, mean, stddev);
mr = mean.at<double>(0, 0);
devr = mean.at<double>(0, 0);
meanStdDev(G, mean, stddev);
mg = mean.at<double>(0, 0);
devg = mean.at<double>(0, 0);
int width = src.cols;
int height = src.rows;
// 反向投影
float pr = 0, pg = 0;
Mat result = Mat::zeros(src.size(), CV_32FC1);
for(int row = 0; row < height; row++) {
uchar* currentRow = src.ptr<uchar>(row);
for(int col = 0; col < width; col++) {
b = *currentRow++;
g = *currentRow++;
r = *currentRow++;
sum = b + g + r;
float red = r / sum;
float green = g / sum;
pr = (1/ (devr*sqrt(2* CV_PI)))*exp(-(pow((red - mr), 2)) / (2* pow(devr, 2)));
pg = (1/ (devg*sqrt(2* CV_PI)))*exp(-(pow((green - mg),2)) / (2* pow(devg, 2)));
sum = pr*pg;
result.at<float>(row, col) = sum;
}
}
// 归一化显示高斯反向投影
Mat img(src.size(), CV_8UC1);
normalize(result, result, 0, 255, NORM_MINMAX);
result.convertTo(img, CV_8U);
Mat segmentation;
src.copyTo(segmentation, img);
// 显示
imshow("backprojection demo", img);
imshow("segmentation demo", segmentation);
waitKey(0);
return0;
}
蓝色矩形框为模型,整个图像为测试图像
反向投影结果
分割提取结果
大家看了这个例子总是有点怪怪的,总会想起点什么,如果你能想起点什么的话就是GMM,高斯混合模型,高斯混合模型正是在此基础上进一步演化而来。
好消息,小白学视觉团队的知识星球开通啦,为了感谢大家的支持与厚爱,团队决定将价值149元的知识星球现时免费加入。各位小伙伴们要抓住机会哦!
交流群
欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~
本文分享自微信公众号 - 小白学视觉(NoobCV)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。