1.OpenCV自带的CamShift算法(例程)解读:
https://blog.csdn.net/kilotwo/article/details/89053311?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control
CamShift使用的算法(Mean Shift)原理解读:
https://blog.csdn.net/zhjm07054115/article/details/24669145
2.首先,Camshift一般使用彩色直方图进行匹配,而红外视频为灰度图像,所以我们需要进行图像的转换。
一般彩色RGB到灰度图像转换公式如下:
Gray = R0.299 + G0.587 + B0.114
而实际应用时,希望避免低速的浮点运算,所以需要整数算法。
注意到系数都是3位精度,我们可以将它们缩放1000倍来实现整数运算算法:
Gray = (R299 + G587 + B114 + 500) / 1000
由于该算法需要32位运算,所以该公式的另一个变种很流行:
Gray = (R30 + G59 + B*11 + 50) / 100
整数移位算法
上面的整数算法已经很快了,但是有一点仍制约速度,就是最后的那个除法。移位比除法快多了,所以可以将系数缩放成2的整数幂。
习惯上使用16位精度,2的16次幂是65536,所以这样计算系数:
0.299 65536 = 19595.264 ≈ 19595
0.587 65536 + (0.264) = 38469.632 + 0.264 = 38469.896 ≈ 38469
0.114 * 65536 + (0.896) = 7471.104 + 0.896 = 7472
2至20位精度的系数:
Gray = (R1 + G2 + B1) >> 2
Gray = (R2 + G5 + B1) >> 3
Gray = (R4 + G10 + B2) >> 4
Gray = (R9 + G19 + B4) >> 5
Gray = (R19 + G37 + B8) >> 6
Gray = (R38 + G75 + B15) >> 7
Gray = (R76 + G150 + B30) >> 8
Gray = (R153 + G300 + B59) >> 9
Gray = (R306 + G601 + B117) >> 10
Gray = (R612 + G1202 + B234) >> 11
Gray = (R1224 + G2405 + B467) >> 12
Gray = (R2449 + G4809 + B934) >> 13
Gray = (R4898 + G9618 + B1868) >> 14
Gray = (R9797 + G19235 + B3736) >> 15
Gray = (R19595 + G38469 + B7472) >> 16
Gray = (R39190 + G76939 + B14943) >> 17
Gray = (R78381 + G153878 + B29885) >> 18
Gray = (R156762 + G307757 + B59769) >> 19
Gray = (R313524 + G615514 + B*119538) >> 20
仔细观察上面的等式,这些精度实际上是一样的:3与4、7与8、10与11、13与14、19与20
所以16位运算下最好的计算公式是使用7位精度,比先前那个系数缩放100倍的精度高,而且速度快:
Gray = (R38 + G75 + B*15) >> 7
其实最有意思的还是那个2位精度的,完全可以移位优化:
Gray = (R + (WORD)G<<1 + B) >> 2
3.红外视频到彩虹图的换算:
内容转载自博客:http://blog.sina.com.cn/s/blog_8924265b0101ext1.html
将灰度图像的灰度值分别转换为RBG三原色,生成伪彩色。
彩虹图一般为
// 红 255, 0, 0 255
// 橙 255, 127, 0 204
// 黄 255, 255, 0 153
// 绿 0, 255, 0 102
// 青 0, 255, 255 51
// 蓝 0, 0, 255 0
六种颜色。需要把0-255分成6段,每段51
转换成彩虹图之后,运用camshift进行跟踪即可。
4.具体实现:在opencv的camshift例程中,找到主函数中的frame.copyTo(image)一句,在这之后加入以下代码:
Mat test(image.rows, image.cols, CV_8UC3);//RGB图像
Mat test_grey;
cvtColor(image, test_grey, COLOR_BGR2GRAY);
int tmp = 0;
Mat img;
cvtColor(image, img, COLOR_BGR2GRAY);
Mat img_color(image.rows, image.cols, CV_8UC3);//构造RGB图像
#define IMG_B(img,y,x)img.at<Vec3b>(y,x)[0]
#define IMG_G(img,y,x)img.at<Vec3b>(y,x)[1]
#define IMG_R(img,y,x)img.at<Vec3b>(y,x)[2]
uchar tmp2 = 0;
for (int y = 0; y<img.rows; y++)//转为彩虹图的具体算法,主要思路是把灰度图对应的0~255的数值分别转换成彩虹色:红、橙、黄、绿、青、蓝。
{
for (int x = 0; x<img.cols; x++)
{
tmp2 = img.at<uchar>(y, x);
if (tmp2 <= 51)
{
IMG_B(img_color, y, x) = 255;
IMG_G(img_color, y, x) = tmp2 * 5;
IMG_R(img_color, y, x) = 0;
}
else if(tmp2 <= 102)
{
tmp2 -= 51;
IMG_B(img_color, y, x) = 255 - tmp2 * 5;
IMG_G(img_color, y, x) = 255;
IMG_R(img_color, y, x) = 0;
}
else if(tmp2 <= 153)
{
tmp2 -= 102;
IMG_B(img_color, y, x) = 0;
IMG_G(img_color, y, x) = 255;
IMG_R(img_color, y, x) = tmp2 * 5;
}
else if(tmp2 <= 204)
{
tmp2 -= 153;
IMG_B(img_color, y, x) = 0;
IMG_G(img_color, y, x) = 255 - uchar(128.0*tmp2 / 51.0 + 0.5);
IMG_R(img_color, y, x) = 255;
}
else
{
tmp2 -= 204;
IMG_B(img_color, y, x) = 0;
IMG_G(img_color, y, x) = 127 - uchar(127.0*tmp2 / 51.0 + 0.5);
IMG_R(img_color, y, x) = 255;
}
}
}
imshow("CamShift", image);
image = img_color;