|
@@ -3,66 +3,76 @@ import java.io.PrintWriter;
|
|
|
import java.util.ArrayList;
|
|
|
|
|
|
public class MeanShift {
|
|
|
- public ArrayList<Double> pointx;
|
|
|
- public ArrayList<Double> pointy;
|
|
|
+ public ArrayList<Double> pointx;//所有点的x坐标集
|
|
|
+ public ArrayList<Double> pointy;//所有点的y坐标集
|
|
|
public double R;
|
|
|
ArrayList<Double> centerx_history_forArea = new ArrayList<>();
|
|
|
ArrayList<Double> centery_history_forArea = new ArrayList<>();
|
|
|
ArrayList<ResultDataType> result = new ArrayList<>();
|
|
|
- public void setPointxAndPonty(ArrayList<Double> pointx_input,ArrayList<Double> pointy_input){
|
|
|
+ public void setPointxAndPointy(ArrayList<Double> pointx_input, ArrayList<Double> pointy_input){
|
|
|
this.pointx = pointx_input;
|
|
|
this.pointy = pointy_input;
|
|
|
}
|
|
|
- public void setR(double R_input){
|
|
|
- this.R = R_input;
|
|
|
+ public void setR(double rinput){
|
|
|
+ this.R = rinput;
|
|
|
}
|
|
|
|
|
|
- public ArrayList<Integer> DL(ArrayList<Integer> NumList){
|
|
|
- for(int i = 0;i < NumList.size();i++){
|
|
|
- int temp_index = (int)(Math.random()*(NumList.size() - i)) + i;
|
|
|
- int temp = NumList.get(i);
|
|
|
- NumList.set(i,NumList.get(temp_index));
|
|
|
- NumList.set(temp_index,temp);
|
|
|
+
|
|
|
+ //洗牌算法,打乱ArrayList
|
|
|
+ public ArrayList<Integer> shuffle(ArrayList<Integer> list){
|
|
|
+ for(int i = 0;i < list.size();i++){
|
|
|
+ int temp_index = (int)(Math.random()*(list.size() - i)) + i;
|
|
|
+ int temp = list.get(i);
|
|
|
+ list.set(i,list.get(temp_index));
|
|
|
+ list.set(temp_index,temp);
|
|
|
}
|
|
|
- return NumList;
|
|
|
+ return list;
|
|
|
}
|
|
|
|
|
|
- public Integer PickUpAPointNum(ArrayList<Integer> NumListLeft){
|
|
|
- NumListLeft = DL(NumListLeft);
|
|
|
- return NumListLeft.get(0);
|
|
|
+
|
|
|
+ //从一个元素为整数的ArrayList里随机挑选一个元素
|
|
|
+ public Integer pickUpAPointNum(ArrayList<Integer> numListLeft){
|
|
|
+ numListLeft = shuffle(numListLeft);
|
|
|
+ return numListLeft.get(0);
|
|
|
}
|
|
|
|
|
|
- public ArrayList<Integer> FindPointinsideR(double centerx,double centery){
|
|
|
+
|
|
|
+ //记录下点集里,距离圆心(centerX,centerY)的距离小于R的所有点的index
|
|
|
+ public ArrayList<Integer> findPointinsideR(double centerX, double centerY){
|
|
|
ArrayList<Integer> NuminsideR = new ArrayList<>();
|
|
|
for(int i = 0 ; i < pointx.size() ; i++){
|
|
|
- if (CalculateDistance(pointx.get(i),pointy.get(i),centerx,centery) < R){
|
|
|
+ if (calculateDistance(pointx.get(i),pointy.get(i),centerX,centerY) < R){
|
|
|
NuminsideR.add(i);
|
|
|
}
|
|
|
}
|
|
|
return NuminsideR;
|
|
|
}
|
|
|
|
|
|
- public double CalculateDistance(Double x1,Double y1, Double x2 ,Double y2){
|
|
|
+ //计算两点之间的距离
|
|
|
+ public double calculateDistance(Double x1, Double y1, Double x2 , Double y2){
|
|
|
return Math.sqrt(Math.pow((x1-x2),2) + Math.pow((y1-y2),2));
|
|
|
}
|
|
|
|
|
|
- public double[] CalculateMh(ArrayList<Integer> NuminsideR,double centerx,double centery){
|
|
|
- double Sumx = 0.;
|
|
|
- double Sumy = 0.;
|
|
|
- double[] mh = new double[2];
|
|
|
- for(int i = 0 ; i < NuminsideR.size();i++){
|
|
|
- Sumx = Sumx + pointx.get(NuminsideR.get(i)) - centerx;
|
|
|
- Sumy = Sumy + pointy.get(NuminsideR.get(i)) - centery;
|
|
|
+
|
|
|
+ //计算平均向量
|
|
|
+ public double[] calculateMeanVector(ArrayList<Integer> indexOfPointInsideR, double centerX, double centerY){
|
|
|
+ double sumX = 0.;
|
|
|
+ double sumY = 0.;
|
|
|
+ double[] meanVector = new double[2];
|
|
|
+ for(int i = 0 ; i < indexOfPointInsideR.size();i++){
|
|
|
+ sumX = sumX + pointx.get(indexOfPointInsideR.get(i)) - centerX;
|
|
|
+ sumY = sumY + pointy.get(indexOfPointInsideR.get(i)) - centerY;
|
|
|
}
|
|
|
|
|
|
- mh[0] = Sumx/NuminsideR.size();
|
|
|
- mh[1] = Sumy/NuminsideR.size();
|
|
|
- return mh;
|
|
|
+ meanVector[0] = sumX/indexOfPointInsideR.size();
|
|
|
+ meanVector[1] = sumY/indexOfPointInsideR.size();
|
|
|
+ return meanVector;
|
|
|
}
|
|
|
|
|
|
+ //比较圆心分别为(x1,y1)和(x2,y2)的两个圆,哪个圆内的点的数量更多。
|
|
|
public boolean judgeDensity(double x1,double y1,double x2,double y2){
|
|
|
- int N_old = FindPointinsideR(x1,y1).size();
|
|
|
- int N_new = FindPointinsideR(x2,y2).size();
|
|
|
+ int N_old = findPointinsideR(x1,y1).size();
|
|
|
+ int N_new = findPointinsideR(x2,y2).size();
|
|
|
if (N_old >= N_new){
|
|
|
return true;
|
|
|
}
|
|
@@ -70,143 +80,157 @@ public class MeanShift {
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
- public ArrayList<ResultDataType> MainLoop() throws FileNotFoundException {
|
|
|
- ArrayList<Integer> numlist = new ArrayList<>();
|
|
|
- ArrayList<Integer> numlist_used = new ArrayList<>();
|
|
|
- ArrayList<Integer> numlist_class = new ArrayList<>();
|
|
|
- ArrayList<Integer> numlist_unused = new ArrayList<>();
|
|
|
- ArrayList<Integer> numlist_center = new ArrayList<>();
|
|
|
- ArrayList<Double> centerx_history = new ArrayList<>();
|
|
|
- ArrayList<Double> centery_history = new ArrayList<>();
|
|
|
- for (int i = 0; i < pointx.size() ; i++){
|
|
|
- numlist.add(i);
|
|
|
+
|
|
|
+ //
|
|
|
+ public ArrayList<ResultDataType> mainLoop() throws FileNotFoundException {
|
|
|
+ ArrayList<Integer> numList = new ArrayList<>();
|
|
|
+ ArrayList<Integer> numListUsed = new ArrayList<>();
|
|
|
+ ArrayList<Integer> numListClass = new ArrayList<>();
|
|
|
+ ArrayList<Integer> numListUnused = new ArrayList<>();
|
|
|
+ ArrayList<Integer> numListCenter = new ArrayList<>();
|
|
|
+ ArrayList<Double> centerXHistory = new ArrayList<>();
|
|
|
+ ArrayList<Double> centerYHistory = new ArrayList<>();
|
|
|
+
|
|
|
+ for (int i = 0; i < pointx.size() ; i++){//把所有点的index存入numList
|
|
|
+ numList.add(i);
|
|
|
}
|
|
|
- numlist_unused = numlist;
|
|
|
- int count_for_outside_loop = 0;
|
|
|
- while (!numlist_unused.isEmpty()){
|
|
|
- count_for_outside_loop = count_for_outside_loop + 1;
|
|
|
- int num = PickUpAPointNum(numlist_unused);
|
|
|
- ArrayList<Integer> NuminsideR = new ArrayList<>();
|
|
|
- double centerx = pointx.get(num);
|
|
|
- double centery = pointy.get(num);
|
|
|
- int inital_num = num;
|
|
|
- System.out.println("the NO. " + count_for_outside_loop + " outside loop and num picked is " + inital_num);
|
|
|
- double inital_centerx = centerx;
|
|
|
- double inital_centery = centery;
|
|
|
- double centerx_next_test ;
|
|
|
- double centery_next_test ;
|
|
|
- int count_for_inside_loop = 0;
|
|
|
+
|
|
|
+ numListUnused = numList;//初始所有的点都是没有被当做圆心的
|
|
|
+ int counterForOutsideLoop = 0;//外循环计数器
|
|
|
+
|
|
|
+ while (!numListUnused.isEmpty()){
|
|
|
+ counterForOutsideLoop = counterForOutsideLoop + 1;
|
|
|
+ int num = pickUpAPointNum(numListUnused);//从还没被选中过作为圆心的点中随机挑选一个,
|
|
|
+ ArrayList<Integer> indexOfPointsInsideR = new ArrayList<>();//在圆内的点的序号
|
|
|
+ double centerX = pointx.get(num);
|
|
|
+ double centerY = pointy.get(num);
|
|
|
+ int inital_num = num;//圆心的点的序号
|
|
|
+ System.out.println("the NO. " + counterForOutsideLoop + " outside loop and num picked is " + inital_num);
|
|
|
+ double inital_centerx = centerX;
|
|
|
+ double inital_centery = centerY;
|
|
|
+ double centerXNextTest ;//下一个圆心的横坐标
|
|
|
+ double centerYNextTest ;//下一个圆心的纵坐标
|
|
|
+ int counterForInsideLoop = 0;//内循环计数器
|
|
|
while(true){
|
|
|
- count_for_inside_loop = count_for_inside_loop + 1;
|
|
|
- NuminsideR = FindPointinsideR(centerx,centery);
|
|
|
- double[] mh = CalculateMh(NuminsideR,centerx,centery);
|
|
|
- centerx_next_test = centerx + mh[0];
|
|
|
- centery_next_test = centery + mh[1];
|
|
|
- if(!judgeDensity(centerx,centery,centerx_next_test,centery_next_test)){
|
|
|
- System.out.println("第 " + count_for_outside_loop + " 次外循环的第 " + count_for_inside_loop + " 次漂移");
|
|
|
- System.out.println("当前圆心为" + centerx + " " + centery);
|
|
|
- System.out.println("当前圆内点个数为:" + NuminsideR.size());
|
|
|
- centerx = centerx_next_test;
|
|
|
- centery = centery_next_test;
|
|
|
+ counterForInsideLoop = counterForInsideLoop + 1;
|
|
|
+ indexOfPointsInsideR = findPointinsideR(centerX,centerY);//圆心为(centerX,centerY)的圆内的所有点的序号
|
|
|
+ double[] meanVector = calculateMeanVector(indexOfPointsInsideR,centerX,centerY);//偏移向量
|
|
|
+ centerXNextTest = centerX + meanVector[0];//下一个圆心的横坐标
|
|
|
+ centerYNextTest = centerY + meanVector[1];//下一个圆心的纵坐标
|
|
|
+ if(!judgeDensity(centerX,centerY,centerXNextTest,centerYNextTest)){//只有当下一个圆内的点更多才会触发偏移
|
|
|
+ System.out.println("第 " + counterForOutsideLoop + " 次外循环的第 " + counterForInsideLoop + " 次漂移");
|
|
|
+ System.out.println("当前圆心为" + centerX + " " + centerY);
|
|
|
+ System.out.println("当前圆内点个数为:" + indexOfPointsInsideR.size());
|
|
|
+ centerX = centerXNextTest;//
|
|
|
+ centerY = centerYNextTest;//
|
|
|
}
|
|
|
else{
|
|
|
- System.out.println("第 " + count_for_outside_loop + " 次外循环,漂移结束。");
|
|
|
+ System.out.println("第 " + counterForOutsideLoop + " 次外循环,漂移结束。");
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
int max = 0;
|
|
|
int compare_density_count=0;
|
|
|
ArrayList<Integer> count_num_cd = new ArrayList<>();
|
|
|
- for(int i = 0 ; i < centerx_history.size();i++){
|
|
|
- if(CalculateDistance(centerx,centery,centerx_history.get(i),centery_history.get(i)) < 2*R){
|
|
|
- count_num_cd.add(i);
|
|
|
+ for(int i = 0 ; i < centerXHistory.size();i++){
|
|
|
+ if(calculateDistance(centerX,centerY,centerXHistory.get(i),centerYHistory.get(i)) < 2*R){//
|
|
|
+ count_num_cd.add(i);//所有与当前圆发生重叠的历史圆
|
|
|
}
|
|
|
else {
|
|
|
max += 1;
|
|
|
}
|
|
|
}
|
|
|
- if(max == centerx_history.size()){
|
|
|
- System.out.println("第 " + count_for_outside_loop + " 次外循环。该循环的圆心和历史收敛圆心距离大于2R。");
|
|
|
- centerx_history.add(centerx);
|
|
|
- centery_history.add(centery);
|
|
|
- numlist_center.add(num);
|
|
|
- numlist_class.addAll(NuminsideR);
|
|
|
- ArrayList<Integer> numlist_used_forcal = new ArrayList<>(numlist_used);
|
|
|
- ArrayList<Integer> numlist_unused_forcal = new ArrayList<>(numlist_unused);
|
|
|
- ArrayList<Integer> numlist_class_forcal = new ArrayList<>(numlist_class);
|
|
|
- ArrayList<Integer> numlist_center_forcal = new ArrayList<>(numlist_center);
|
|
|
- ArrayList<Integer> numlist_forcal = new ArrayList<>(numlist);
|
|
|
+ if(max == centerXHistory.size()){//所有历史圆心与该圆心的距离大于2R,该圆心直接被收集到centerX,YHistory中
|
|
|
+ System.out.println("第 " + counterForOutsideLoop + " 次外循环。该循环的圆心和历史收敛圆心距离大于2R。");
|
|
|
+ centerXHistory.add(centerX);
|
|
|
+ centerYHistory.add(centerY);
|
|
|
+ numListCenter.add(num);
|
|
|
+ numListClass.addAll(indexOfPointsInsideR);
|
|
|
+ ArrayList<Integer> numlist_used_forcal = new ArrayList<>(numListUsed);
|
|
|
+ ArrayList<Integer> numlist_unused_forcal = new ArrayList<>(numListUnused);
|
|
|
+ ArrayList<Integer> numlist_class_forcal = new ArrayList<>(numListClass);//
|
|
|
+ ArrayList<Integer> numlist_center_forcal = new ArrayList<>(numListCenter);
|
|
|
+ ArrayList<Integer> numlist_forcal = new ArrayList<>(numList);
|
|
|
numlist_class_forcal.removeAll(numlist_center_forcal);
|
|
|
+
|
|
|
numlist_center_forcal.addAll(numlist_center_forcal);
|
|
|
numlist_used_forcal = numlist_center_forcal;
|
|
|
numlist_forcal.removeAll(numlist_used_forcal);
|
|
|
numlist_unused_forcal = numlist_forcal;
|
|
|
- numlist_unused = numlist_unused_forcal;
|
|
|
+ numListUnused = numlist_unused_forcal;
|
|
|
}
|
|
|
- else{
|
|
|
+ else{//发生重叠
|
|
|
ArrayList<Integer> cd_NuminsideR = new ArrayList<>();
|
|
|
- System.out.println("第 " + count_for_outside_loop + " 次外循环。当前收敛的圆和历史部分圆重叠。");
|
|
|
+ System.out.println("第 " + counterForOutsideLoop + " 次外循环。当前收敛的圆和历史部分圆重叠。");
|
|
|
System.out.println("重叠了 " + count_num_cd.size() + " 个");
|
|
|
|
|
|
for (int i = 0 ; i < count_num_cd.size(); i++){
|
|
|
- int length = FindPointinsideR(centerx_history.get(count_num_cd.get(i)),centery_history.get(count_num_cd.get(i))).size();
|
|
|
- cd_NuminsideR.add(length);
|
|
|
+ int length = findPointinsideR(centerXHistory.get(count_num_cd.get(i)),centerYHistory.get(count_num_cd.get(i))).size();
|
|
|
+ cd_NuminsideR.add(length);//和当前漂移后的圆发生重叠的历史圆的包含点数
|
|
|
}
|
|
|
int temp_for_count_num_cd = count_num_cd.size();
|
|
|
ArrayList<Double> centerx_history_to_disappear = new ArrayList<>();
|
|
|
ArrayList<Double> centery_history_to_disappear = new ArrayList<>();
|
|
|
for(int i = 0 ; i < temp_for_count_num_cd ; i++){
|
|
|
- if(NuminsideR.size() > cd_NuminsideR.get(i)){
|
|
|
+ if(indexOfPointsInsideR.size() > cd_NuminsideR.get(i)){
|
|
|
compare_density_count = compare_density_count + 1;
|
|
|
- ArrayList<Integer> the_circle_disappear= FindPointinsideR(centerx_history.get(count_num_cd.get(i)),centery_history.get(count_num_cd.get(i)));
|
|
|
- centerx_history_to_disappear.add(centerx_history.get(count_num_cd.get(i)));
|
|
|
- centery_history_to_disappear.add(centery_history.get(count_num_cd.get(i)));
|
|
|
- numlist_class.removeAll((ArrayList<Integer>)the_circle_disappear);
|
|
|
+ ArrayList<Integer> the_circle_disappear= findPointinsideR(centerXHistory.get(count_num_cd.get(i)),centerYHistory.get(count_num_cd.get(i)));
|
|
|
+ centerx_history_to_disappear.add(centerXHistory.get(count_num_cd.get(i)));
|
|
|
+ centery_history_to_disappear.add(centerYHistory.get(count_num_cd.get(i)));
|
|
|
+ numListClass.removeAll((ArrayList<Integer>)the_circle_disappear);
|
|
|
}
|
|
|
}
|
|
|
for(int i = 0 ; i < centerx_history_to_disappear.size(); i++){
|
|
|
- centerx_history.remove(centerx_history_to_disappear.get(i));
|
|
|
- centery_history.remove(centery_history_to_disappear.get(i));
|
|
|
+ centerXHistory.remove(centerx_history_to_disappear.get(i));
|
|
|
+ centerYHistory.remove(centery_history_to_disappear.get(i));
|
|
|
}
|
|
|
if(compare_density_count == cd_NuminsideR.size()){
|
|
|
System.out.println("当前收敛圆比和它重叠的历史收敛的圆密度都大");
|
|
|
- centerx_history.add(centerx);
|
|
|
- centery_history.add(centery);
|
|
|
- numlist_center.add(num);
|
|
|
- numlist_class.addAll(NuminsideR);
|
|
|
- ArrayList<Integer> numlist_used_forcal = new ArrayList<>(numlist_used);
|
|
|
- ArrayList<Integer> numlist_unused_forcal = new ArrayList<>(numlist_unused);
|
|
|
- ArrayList<Integer> numlist_class_forcal = new ArrayList<>(numlist_class);
|
|
|
- ArrayList<Integer> numlist_center_forcal = new ArrayList<>(numlist_center);
|
|
|
- ArrayList<Integer> numlist_forcal = new ArrayList<>(numlist);
|
|
|
+ centerXHistory.add(centerX);
|
|
|
+ centerYHistory.add(centerY);
|
|
|
+
|
|
|
+
|
|
|
+ numListCenter.add(num);
|
|
|
+ numListClass.addAll(indexOfPointsInsideR);
|
|
|
+ ArrayList<Integer> numlist_used_forcal = new ArrayList<>(numListUsed);
|
|
|
+ ArrayList<Integer> numlist_unused_forcal = new ArrayList<>(numListUnused);
|
|
|
+
|
|
|
+ //forcal是为了在不影响原有的arraylist前提下,用原有的arraylist参与计算
|
|
|
+ ArrayList<Integer> numlist_class_forcal = new ArrayList<>(numListClass);
|
|
|
+ ArrayList<Integer> numlist_center_forcal = new ArrayList<>(numListCenter);
|
|
|
+ ArrayList<Integer> numlist_forcal = new ArrayList<>(numList);
|
|
|
numlist_class_forcal.removeAll(numlist_center_forcal);
|
|
|
- numlist_center_forcal.addAll(numlist_center_forcal);
|
|
|
+
|
|
|
+// numlist_center_forcal.addAll(numlist_center_forcal);
|
|
|
+ numlist_center_forcal.addAll(numlist_class_forcal);
|
|
|
numlist_used_forcal = numlist_center_forcal;
|
|
|
numlist_forcal.removeAll(numlist_used_forcal);
|
|
|
numlist_unused_forcal = numlist_forcal;
|
|
|
- numlist_unused = numlist_unused_forcal;
|
|
|
+ numListUnused = numlist_unused_forcal;//所有未使用过的点,既包含圆心也包含被圆心所代表的圆围住的点
|
|
|
}
|
|
|
+ ///当前收敛圆和部分历史圆重叠
|
|
|
}
|
|
|
- numlist_unused.remove((Integer)inital_num);
|
|
|
+ numListUnused.remove((Integer)inital_num);//外循环是从未使用过的点里随机挑一个出来的,这个点也必须从未使用的点序号列表里清除。
|
|
|
}
|
|
|
- for(int i = 0 ; i < centerx_history.size();i++){
|
|
|
- ArrayList<Integer> out_NuminsideR = FindPointinsideR(centerx_history.get(i),centery_history.get(i));
|
|
|
+ ///////
|
|
|
+ for(int i = 0 ; i < centerXHistory.size();i++){
|
|
|
+ ArrayList<Integer> out_NuminsideR = findPointinsideR(centerXHistory.get(i),centerYHistory.get(i));
|
|
|
result.add(new ResultDataType(out_NuminsideR));
|
|
|
}
|
|
|
- for (int i = 0 ; i < centerx_history.size() - 1; i++){
|
|
|
- for (int j = i+1 ; j < centerx_history.size(); j++){
|
|
|
- double temp =CalculateDistance(centerx_history.get(i),centery_history.get(i),centerx_history.get(j),centery_history.get(j));
|
|
|
+ for (int i = 0 ; i < centerXHistory.size() - 1; i++){
|
|
|
+ for (int j = i+1 ; j < centerXHistory.size(); j++){
|
|
|
+ double temp = calculateDistance(centerXHistory.get(i),centerYHistory.get(i),centerXHistory.get(j),centerYHistory.get(j));
|
|
|
System.out.println("ths distance is " + temp);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
java.io.File file3 = new java.io.File("C:\\Users\\87969\\Desktop\\test\\meanshiftLastcircle.txt");
|
|
|
PrintWriter TestData_OutPut = new PrintWriter(file3);
|
|
|
- for(int i = 0; i < centerx_history.size();i++){
|
|
|
- TestData_OutPut.println(centerx_history.get(i) + " " + centery_history.get(i));
|
|
|
+ for(int i = 0; i < centerXHistory.size();i++){
|
|
|
+ TestData_OutPut.println(centerXHistory.get(i) + " " + centerYHistory.get(i));
|
|
|
}
|
|
|
- centerx_history_forArea = centerx_history;
|
|
|
- centery_history_forArea = centery_history;
|
|
|
+ centerx_history_forArea = centerXHistory;
|
|
|
+ centery_history_forArea = centerYHistory;
|
|
|
TestData_OutPut.close();
|
|
|
return result;
|
|
|
}
|