• 利用opencv3中的kmeans实现抠图功能


    kmeans算法主要用来实现自动聚类,是一种非监督的机器学习算法,使用非常广泛。在opencv3.0中提供了这样一个函数,直接调用就能实现自动聚类,非常方便。

    函数原型:

    C++: double kmeans(InputArray data, int K, InputOutputArray bestLabels, TermCriteria criteria, int attempts, int flags, OutputArray centers=noArray() )

    有7个参数,分别表示:

    data:  需要自动聚类的数据,一般是一个Mat。浮点型的矩阵,每行为一个样本。

    k: 取成几类,比较关键的一个参数。

    bestLabels:  返回的类别标记,整型数字。

    criteria: 算法结束的标准,获取期望精度的迭代最大次数

    attempts:  判断某个样本为某个类的最少聚类次数,比如值为3时,则某个样本聚类3次都为同一个类,则确定下来。

    flags:  确定簇心的计算方式。有三个值可选:KMEANS_RANDOM_CENTERS 表示随机初始化簇心。KMEANS_PP_CENTERS 表示用kmeans++算法来初始化簇心(没用过),KMEANS_USE_INITIAL_LABELS 表示第一次聚类时用用户给定的值初始化聚类,后面几次的聚类,则自动确定簇心。

    centers: 用来初始化簇心的。与前一个flags参数的选择有关。如果选择KMEANS_RANDOM_CENTERS随机初始化簇心,则这个参数可省略。

    示例图片:

    学过ps描图的都知道,头发丝在抠图中,是非常难的。这里我们就用kmeans自动聚类来进行自动抠图。

    思路就是将图片的每个像素点的三通道值作为一个特征,因此会得到一个n行3列的特征矩阵data,然后用这个特征矩阵进行kmeans

    代码:

    #include "stdafx.h"
    #include "opencv2opencv.hpp"
    #include <iostream>
    using namespace std;
    using namespace cv;
    int main()
    {
        const int MAX_CLUSTERS = 5;
        Vec3b colorTab[] =
        {
            Vec3b(0, 0, 255),
            Vec3b(0, 255, 0),
            Vec3b(255, 100, 100),
            Vec3b(255, 0, 255),
            Vec3b(0, 255, 255)
        };
        Mat data,labels;
        Mat pic = imread("d:/woman.png");
        for (int i = 0; i < pic.rows;i++)
        for (int j = 0; j < pic.cols; j++)
        {
            Vec3b point = pic.at<Vec3b>(i, j);
            Mat tmp = (Mat_<float>(1, 3) << point[0], point[1], point[2]);
            data.push_back(tmp);
        }
    
        //根据浏览图片,确定k=3
        kmeans(data, 3, labels, TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0),
            3, KMEANS_RANDOM_CENTERS);
    
        int n = 0;
        //显示聚类结果,不同的类别用不同的颜色显示
        for (int i = 0; i < pic.rows; i++)
        for (int j = 0; j < pic.cols; j++)
        {
            int clusterIdx = labels.at<int>(n);
            pic.at<Vec3b>(i, j) = colorTab[clusterIdx];
            n++;
        }
        imshow("pic", pic);
        waitKey(0);
        
        return 0;
    }

    结果:

    效果不是十分理想,毕竟是全自动的。

  • 相关阅读:
    微信小程序开发入门(二)
    微信小程序开发入门(一)
    django入门与实践(续)
    django入门与实践(开)
    Python六剑客
    python入门(二十讲):爬虫
    python入门(十九讲):多进程
    ES6箭头函数
    ES6
    数据库常用命令
  • 原文地址:https://www.cnblogs.com/denny402/p/5033380.html
Copyright © 2020-2023  润新知