AI识别物体是比较成熟的技术,然而在场景比较单一的地方,用AI做视频感觉有点大材小用。
其实在场景比较单一的情况下,很多实例都可以通过颜色来区分不同的物体,但是我们知道,在实际应用中,总会有光照或者其他的影响,加大我们的颜色判断难度。我这里根据我的业务场景找到一个比较好的红色提取思路。
我是对每个三通道的像素点进行分析:
- 将图片从其他格式转换为rgb
- 红色像素值最大,且大于0x55
- 其他通道像素值的距离比较小,且与红色像素值的距离比率较大,且大于10。
int is_red_point(unsigned char color[3])
{
int t[3];
for (int i = 0; i < 3; i++)
{
t[i] = color[i] - color[(i + 1) % 3];
}
if (t[0] > 0 && t[2] < 0 && abs(t[1]) * 5 < t[0] && color[0] > 0x55 && t[0] > 10)
{
return 1;
}
return 0;
}
整个代码:
#include <stdio.h>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int is_red_point(unsigned char color[3])
{
int t[3];
for (int i = 0; i < 3; i++)
{
t[i] = color[i] - color[(i + 1) % 3];
}
if (t[0] > 0 && t[2] < 0 && abs(t[1]) * 5 < t[0] && color[0] > 0x55 && t[0] > 10)
{
return 1;
}
return 0;
}
int main(int argc, char *argv[])
{
//通过图片进行测试
const char *video_path = "1555645683653_1.jpg";
Mat im = imread(video_path);
imshow("abc1", im);
// 转换为rgb
Mat im_rgb;
cvtColor(im, im_rgb, CV_BGR2RGB);
Mat img = Mat(im.rows, im.cols, CV_8UC1);
printf("%d, %d, %ld, %ld, %ld\n", im.rows, im.cols, im.step[0], im.step[1], im.step[2]);
for (int i = 0; i < im_rgb.rows; i++)
{
for (int j = 0; j < im_rgb.cols; j++)
{
unsigned char *a = &(im_rgb.data[i * im_rgb.step[0] + j * im_rgb.step[1]]);
if (is_red_point(&(im_rgb.data[i * im_rgb.step[0] + j * im_rgb.step[1]])))
{
img.data[i * im_rgb.cols + j] = 255;
}
else
{
img.data[i * im_rgb.cols + j] = 0;
}
}
}
Mat result;
add(im, NULL, result, img);
imshow("abc", result);
waitKey(0);
// 一个像素点的测试实例
unsigned char test[3] = {0x23, 0, 0xFC};
if (is_red_point(test)) //#2300FC
{
printf("is red!\n");
}
else
{
printf("not red!\n");
}
return 0;
}
原图
通过像素判断处理后的掩码图片覆盖后的图片:
思路很简单,但是从中可以看到,像素值其实有很多关系,找到了关系,处理起来也是比较容易的。