码迷,mamicode.com
首页 > 编程语言 > 详细

手撸kmeans(c++)实现,用于图像的主色调提取(1)

时间:2017-11-01 23:54:44      阅读:321      评论:0      收藏:0      [点我收藏+]

标签:exec   blog   set   rand   ini   find   sig   ++   argv   

想到那天头条面试时,让我手撸kmeans,奈何好久不用c++,好多都忘了==淡淡的忧伤

技术分享

这次刚好赶上机会,可以再试试了,我写成项目了,有多个文件

首先:base.h

#ifndef BASE_H
#define BASE_H
#include<iostream>
#include<opencv2/opencv.hpp>
#include<cassert>
#include<stdlib.h>
class Baseofgeo{
public:
  float computedis(const std::vector<float> p1,const std::vector<float> p2);
  void Gekmeasns(std::vector<std::vector<float> >& listA,int K);
private: 
//to do...
};
#endif

 再上:base.cpp

#include"base.h"

void Baseofgeo::Gekmeasns(std::vector<std::vector<float> >& listA,int K){
  
  //初始化 
   srand((unsigned)time(NULL));   
   std::vector<std::vector<float> > centerid(K,std::vector<float> (3,0.0));
   int len=listA.size(); 
   for (int i=0;i<K;){
     int randomindex=rand()%len;
     if(listA[randomindex][3]!=-1.0){continue;}
     
     listA[randomindex][3]=i;
     centerid[i][0]=listA[randomindex][0];
     centerid[i][1]=listA[randomindex][1];
     centerid[i][2]=listA[randomindex][2];
     i++;
  }

  //计算距离  
  int count=0;//迭代次数
  float J1=0.0;//记录上一次迭代后的类内距离
  float reserror=100.0;//记录连续两次类内距离的变化
  while( count<=20 && reserror>10.0){
   std::cout<<"第"<<count<<"次迭代"<<std::endl; 
    //对每个点遍历,计算与其最接近的中心,并赋上类别
  for(std::vector<float>& p1:listA){
    std::vector<float> pp1(3,0.0);
    pp1[0]=p1[0];pp1[1]=p1[1];pp1[2]=p1[2];
    float mindist=99999999.0;
    for(int j=0;j<centerid.size();j++){
      std::vector<float> p2=centerid[j];
      float distt=computedis(pp1,p2);      
      if(distt<mindist){	
	mindist=distt;
	p1[3]=(float)j;
      }    
    }
        
  }
  //重新计算中心
  for(int i=0;i<K;i++){
    std::vector<float> sum(3,0.0); float numb=0.0;
    for(std::vector<float> p:listA){
      if((int)p[3]==i){
	sum[0]+=p[0];sum[1]+=p[1];sum[2]+=p[2];
	numb++;
      } 
    }
    assert(numb!=0);
    sum[0]/=numb;sum[1]/=numb;sum[2]/=numb;
    centerid[i]=sum;
    
  }

  //计算终止条件1
  count++;
  //计算终止条件2
  float J=0.0;
  for(int i=0;i<K;i++){
    for(std::vector<float> p:listA ){
      if ((int)p[3]==i){
	std::vector<float> ptem(3,0.0);
	ptem[0]=p[0];ptem[1]=p[1];ptem[2]=p[2];
	J+=computedis(ptem,centerid[i]);
      }  
    }   
  }
  //
  if (count==1){
    //记录上次的类内距离之和
    J1=J;
  }else{
    reserror=std::abs(J-J1);
    std::cout<<"reserror:"<<reserror<<std::endl;
    //记录上次的类内距离之和
    J1=J;
  }  
  }   
}

float Baseofgeo::computedis(const std::vector<float> p1,const std::vector<float> p2){
  assert(p1.size()==3&&p2.size()==3);
  return std::sqrt(pow(p1[0]-p2[0],2)+pow(p1[1]-p2[1],2)+pow(p1[2]-p2[2],2));
  
}

主函数嘛:main.cpp

#include<iostream>
#include<vector>
#include<boost/concept_check.hpp>
#include<opencv2/opencv.hpp>
#include<time.h>
#include<stdlib.h>
#include<cassert>
#include<memory>
#include"base.h"

int main(int argc,char** argv){
  
  cv::Mat  I=cv::imread("../data/0001.jpg");
  cv::imshow("im a pic",I);
  std::vector<std::vector<float> >   listA(I.cols*I.rows,std::vector<float>(4,-1.0));
 int nl=d_Ihsv.rows;
 int nc=d_Ihsv.cols;
 int ii=0;
 for(int i=0;i<nl;i++){
   for(int j=0;j<nc;j++){
    listA[ii][0]=I.at<cv::Vec3f>(i,j)[0]/10.0;
    listA[ii][1]=I.at<cv::Vec3f>(i,j)[1]/10.0;
    listA[ii][2]=I.at<cv::Vec3f>(i,j)[2]/10.0;
    ii++;
     
  }
  
}
 std::shared_ptr<Baseofgeo> basemethod(new Baseofgeo());
 basemethod->Gekmeasns(listA,72);
//就当我是可视化==,可视化第二期再更 for(auto p:listA){ std::cout<<p[3]<<std::endl; } return 0; }

还有CMakeLists.txt

cmake_minimum_required( VERSION 2.8 )
project ( image )

set(OpenCV_DIR "/home/geo/opencv-2.4.13/build")
add_compile_options(-std=c++11)

find_package(OpenCV REQUIRED)
add_library(base base.cpp)
target_link_libraries(
  base   ${OpenCV_LIBS}) add_executable(main main.cpp) target_link_libraries(main base ${OpenCV_LIBS})

 

手撸kmeans(c++)实现,用于图像的主色调提取(1)

标签:exec   blog   set   rand   ini   find   sig   ++   argv   

原文地址:http://www.cnblogs.com/geooeg/p/7769048.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!