最近两年,无人驾驶物流配送车出现在各大城市,例如,阿里的小蛮驴,无人车的出现解决了快递配送最后一公里问题,那在AI计算机视觉领域,谁又能充当这个角色呢?
在AI视觉领域,尤其是分割任务,AI框架输出的是二进制的分割结果掩码,通过分割结果可以显示肿瘤的轮廓,但光有肿瘤的解剖结构还不行,医生想要更多的信息,例如,肿瘤的体积,轮廓,横截面最大径等,这就需要其他一些工具在AI分割结果的基础上进行进一步计算,在所有可用的工具中,OpenCV是被使用频率最高的一个。
例如,通过下面三个函数,计算分割结果的边缘,计算轮廓,计算轮廓外接矩形来补充分割结果信息。
CV_EXPORTS_W void Canny( InputArray image, OutputArray edges,
double threshold1, double threshold2,
int apertureSize = 3, bool L2gradient = false )
CV_EXPORTS_W void findContours( InputArray image, OutputArrayOfArrays contours,
OutputArray hierarchy, int mode,
int method, Point offset = Point());
CV_EXPORTS_W RotatedRect minAreaRect( InputArray points );
OpenCV在计算机视觉领域非常强大,集成了各种图像滤波,形态学,分割,模式识别等算法,在人工智能大行其道的今天,OpenCV紧跟时代步伐,在传统算法的基础上,增加了对人工智能的支持。
OpenCV不仅仅只能解决最后一公里问题,它正逐步发展成一个人工智能框架。
推理:
OpenCV的dnn模块,能够解析Pytorch,Tensorflow,ONNX等第三方AI框架训练好的模型参数文件,在产品中对模型进行部署,虽然很多AI框架都提供了针对C++,Python,JS等多种语言的推理框架,但如果只用一种框架就能解决全部问题,那何乐而不为呢?
CV_EXPORTS_W Net readNetFromTorch(const String &model, bool isBinary = true, bool evaluate = true);
CV_EXPORTS NetreadNetFromTensorflow(const char *bufferModel, size_t lenModel,
const char *bufferConfig = NULL, size_t lenConfig = 0);
机器学习算法:
一提到机器学习算法,大家很快都会想到scikit-learn,它确实是一个很强大的机器学习算法库,但它并没有提供多语言的支持,例如,如果我们的项目是C++,可能没办法直接使用scikit-learn,这时OpenCV就是一个不错的选择,下面我们尝试用OpenCV去实现几个常用的机器学习算法。
Kmean:
定义训练数据,坐标位置x,y代表特征
Mat points(sampleCount, 1, CV_32FC2), labels;
设定聚类中心数目,随机生成聚类中心点,并在聚类中心附近随机生成样本点
for( k = 0; k < clusterCount; k++ )
{
Point center;
center.x = rng.uniform(0, img.cols);
center.y = rng.uniform(0, img.rows);
Mat pointChunk = points.rowRange(k*sampleCount/clusterCount,
k == clusterCount - 1 ? sampleCount :
(k+1)*sampleCount/clusterCount);
rng.fill(pointChunk, RNG::NORMAL, Scalar(center.x, center.y), Scalar(img.cols*0.05, img.rows*0.05));
}
randShuffle(points, 1, &rng);
进行聚类
double compactness = kmeans(points, clusterCount, labels,
TermCriteria( TermCriteria::EPS+TermCriteria::COUNT, 10, 1.0),
3, KMEANS_PP_CENTERS, centers);
KNN属于无监督的机器学习方法,训练数据不存在标签值,聚类过程就相当于训练过程,训练完成后生成的模型参数就是聚类中心,当对新的数据进行推理时,只要计算新的数据与所有聚类中心的距离即可。
SVM:
bool doTrain( const Mat samples, const Mat responses, Mat &weights, float &shift)
{
cv::Ptr svmsgd = SVMSGD::create();
cv::Ptr trainData = TrainData::create(samples, cv::ml::ROW_SAMPLE, responses);
svmsgd->train( trainData );
if (svmsgd->isTrained())
{
weights = svmsgd->getWeights();
shift = svmsgd->getShift();
return true;
}
return false;
}
Samples是训练数据的输入特征,responses是标签值,训练完成后输出模型的权重和偏移。
人工神经网络:
除了机器学习算法外,OpenCV还支持人工神经网络的搭建:
定义训练数据输入特征,数据个数100,特征维度100
//create random training data
Mat_ data(100, 100);
randn(data, Mat::zeros(1, 1, data.type()), Mat::ones(1, 1, data.type()));
定义训练数据标签
//half of the samples for each class
Mat_ responses(data.rows, 2);
for (int i = 0; i { } 定义神经网络输入层,隐藏层,输出层神经元个数 Mat_ layerSizes(1, 3); layerSizes(0, 0) = data.cols;输入层神经元个数与数据特征维度一致 layerSizes(0, 1) = 20;隐藏层神经元个数 layerSizes(0, 2) = responses.cols;输出层神经元个数与标签维度一致 定义神经网络 Ptr network->setLayerSizes(layerSizes); 设置激活函数 network->setActivationFunction(ANN_MLP::SIGMOID_SYM, 0.1, 0.1); network->setTrainMethod(ANN_MLP::BACKPROP, 0.1, 0.1); Ptr trainData = TrainData::create(data, ROW_SAMPLE, responses); 模型训练 network->train(trainData); if(network->isTrained()) { printf(“Predict one-vector:\n”); Mat result; network->predict(Mat::ones(1, data.cols, data.type()), result); cout << result << endl; printf(“Predict training data:\n”); for (int i=0; i { network->predict(data.row(i), result);推理 cout << result << endl; } }if (i < data.rows/2)
{
responses(i, 0) = 1;
responses(i, 1) = 0;
}
else
{
responses(i, 0) = 0;
responses(i, 1) = 1;
}