DBSCAN的部分实现(只是找其中一个类)

代码如下:

import math
import cv2
import numpy as np

#二分法查找数据的位置
def finddata(d1,list1,i):#i=0,1
    d1=d1[i]
    list_index_min = 0
    list_index_max = len(list1) - 1

    if d1<=list1[list_index_min][i]:
        return list_index_min
    elif d1>=list1[list_index_max][i]:
        return list_index_max
    else:
        s=-1
        while list_index_min <= list_index_max:
            list_index_middle = (list_index_min + list_index_max) // 2
            if list1[list_index_middle][i] < d1:
                list_index_min = list_index_middle + 1
            elif list1[list_index_middle][i] > d1:
                list_index_max = list_index_middle - 1
            else:
                s=list_index_middle
                break
        if s==-1:
            return list_index_min-1
        else:
            return s


#1.数据处理,将数据处理为二维数组=======>[(0, 3), (1, 1), (1, 2),........, (1, 3), (1, 4), (1, 5)]
def data_set(data):
    list=[]
    for i in range(len(data)):
        for j in range(len(data[0])):
            if data[i][j]!=0:
                list.append((i,j))
    return list


#2.将1的数组转换为字典,方便后续寻找同类的点
  #注意:有两个字典,一个的键是按照行从小到达排列,另一个的键按照列从小到达排列,返回值如下
  #dic1 {'0': [(0, 3)], '1': [(1, 1), (1, 2), (1, 3), (1, 4), (1, 5)], '2': [(2, 1), (2, 2), (2, 3), (2, 4), (2, 5)],.........]
  #dic2 {'0': [(3, 0)], '1': [(1, 1), (2, 1), (3, 1), (4, 1), (5, 1)], '2': [(1, 2), (2, 2), (3, 2), (4, 2), (5, 2)],.........]
def dic1_dic2(datas):
    # 1.对数组分别按照行列进行排序,原数组是按照行排序
    datas=sorted(datas)
    data_over = sorted(datas, key=lambda x: x[1])

    # 2.获得两个行和列从小到达排列的字典
    dic1 = {}
    dic2 = {}

    for item in datas:
        if str(item[0]) not in dic1:
            dic1[str(item[0])]=[]
            dic1[str(item[0])].append(item)
        else:
            dic1[str(item[0])].append(item)

    for item in data_over:
        if str(item[1]) not in dic2:
            dic2[str(item[1])]=[]
            dic2[str(item[1])].append(item)
        else:
            dic2[str(item[1])].append(item)

    return dic1,dic2


#3.获取dic1的第一个键的第一个元素,放入新的字典sigle_dic_class1和sigle_dic_class2,如(0,3)一个的键为0,另一个的键为3
def dic_get_value1(dic1):
    #1.获得字典dic1的键值
    dic1_key =list(dic1.keys())

    sigle_dic_class1 = {}

    # 将dic1的第一个元素设为新的类的第一个元素
    sigle_dic_class1[dic1_key[0]] = []
    sigle_dic_class1[dic1_key[0]].append(dic1[dic1_key[0]][0])
    # dic1[dic1_key[0]].append(dic1[dic1_key[0]][0])

    return sigle_dic_class1

#4.
def row_dic_del(i,out_index,item,list1,classes,dic1,dic2,sigle_dic_class1,sigle_dic_class2):
    out_index2 = out_index
    while out_index >= 0:
        if ((item[i] - dic2[str(item[1 - i])][out_index][i]) ** 2 + (
                item[1 - i] - dic2[str(item[1 - i])][out_index][1 - i]) ** 2) ** 0.5 <= n:
            if str(item[1]) not in sigle_dic_class2:
                sigle_dic_class2[str(item[1 - i])] = []
            sigle_dic_class2[str(item[1 - i])].append(dic2[str(item[1 - i])][out_index])
            dic1[str(dic2[str(item[1 - i])][out_index][i])].remove(dic2[str(item[1 - i])][out_index])

            classes.append(dic2[str(item[1 - i])][out_index])
            ss = dic2[str(item[1 - i])][out_index]  # 10.17号新加
            if dic1[str(dic2[str(item[1 - i])][out_index][i])] == []:  # 如果dic2的某个键的元素为空,则删除该键
                del dic1[str(dic2[str(item[1 - i])][out_index][1])]
                if str(dic2[str(item[1 - i])][out_index][1]) in sigle_dic_class1:
                    del sigle_dic_class1[str(dic2[str(item[1 - i])][out_index][i])]

            dic2[str(item[1 - i])].remove(dic2[str(item[1 - i])][out_index])

            item = ss  # 10.17号新加
            out_index -= 1
        else:
            break

    out_index = out_index2
    while out_index <= len(list1) - 1:
        if ((item[i] - dic2[str(item[1 - i])][out_index][1]) ** 2 + (
                item[1 - i] - dic2[str(item[1 - i])][out_index][1 - i]) ** 2) ** 0.5 <= n:
            if str(item[1 - i]) not in sigle_dic_class2:
                sigle_dic_class2[str(item[1 - i])] = []
            sigle_dic_class2[str(item[1 - i])].append(dic2[str(item[1 - i])][out_index])
            dic1[str(dic2[str(item[1 - i])][out_index][i])].remove(dic2[str(item[1 - i])][out_index])

            classes.append(dic2[str(item[1 - i])][out_index])
            ss=dic2[str(item[1 - i])][out_index]#10.17号新加
            if dic1[str(dic2[str(item[1 - i])][out_index][i])] == []:  # 如果dic2的某个键的元素为空,则删除该键
                del dic1[str(dic2[str(item[1 - i])][out_index][i])]
                if str(dic2[str(item[1 - i])][out_index][i]) in sigle_dic_class1:
                    del sigle_dic_class1[str(dic2[str(item[1 - i])][out_index][i])]

            dic2[str(item[1 - i])].remove(dic2[str(item[1 - i])][out_index])

            item=ss #10.17号新加
            out_index += 1
        else:
            break



def col_dic_del(i,out_index,item,list1,classes,dic1,dic2,sigle_dic_class1,sigle_dic_class2):

    out_index2 = out_index
    while out_index >= 0:
        if ((item[i] - dic1[str(item[1-i])][out_index][i]) ** 2 + (
                item[1-i] - dic1[str(item[1-i])][out_index][1-i]) ** 2) ** 0.5 <= n:
            if str(item[0]) not in sigle_dic_class1:
                sigle_dic_class1[str(item[1-i])] = []
            sigle_dic_class1[str(item[1-i])].append(dic1[str(item[1-i])][out_index])
            dic2[str(dic1[str(item[1-i])][out_index][i])].remove(dic1[str(item[1-i])][out_index])

            classes.append(dic1[str(item[1-i])][out_index])
            ss=dic1[str(item[1-i])][out_index]  #10.17号新加
            if dic2[str(dic1[str(item[1-i])][out_index][i])] == []:  # 如果dic2的某个键的元素为空,则删除该键
                del dic2[str(dic1[str(item[1-i])][out_index][1])]
                if str(dic1[str(item[1-i])][out_index][1]) in sigle_dic_class2:
                    del sigle_dic_class2[str(dic1[str(item[1-i])][out_index][i])]

            dic1[str(item[1-i])].remove(dic1[str(item[1-i])][out_index])

            item=ss #10.17号新加
            out_index -= 1
        else:
            break

    out_index = out_index2
    while out_index <= len(list1) - 1:
        if ((item[i] - dic1[str(item[1-i])][out_index][1]) ** 2 + (
                item[1-i] - dic1[str(item[1-i])][out_index][1-i]) ** 2) ** 0.5 <= n:
            if str(item[1-i]) not in sigle_dic_class1:
                sigle_dic_class1[str(item[1-i])] = []
            sigle_dic_class1[str(item[1-i])].append(dic1[str(item[1-i])][out_index])
            dic2[str(dic1[str(item[1-i])][out_index][i])].remove(dic1[str(item[1-i])][out_index])

            classes.append(dic1[str(item[1-i])][out_index])
            ss = dic1[str(item[1-i])][out_index]  # 10.17号新加
            if dic2[str(dic1[str(item[1-i])][out_index][i])] == []:  # 如果dic2的某个键的元素为空,则删除该键
                del dic2[str(dic1[str(item[1-i])][out_index][i])]
                if str(dic1[str(item[1-i])][out_index][i]) in sigle_dic_class2:
                    del sigle_dic_class2[str(dic1[str(item[1-i])][out_index][i])]

            dic1[str(item[1-i])].remove(dic1[str(item[1-i])][out_index])

            item = ss  # 10.17号新加
            out_index += 1
        else:
            break

def cols(key,item,out_index,dic1,dic2,sigle_dic_class2):
    out_index2=out_index
    while out_index >= 0:
        if ((item[0] - dic2[key][out_index][0]) ** 2 + (item[1] - dic2[key][out_index][1]) ** 2) ** 0.5 <= n:
            sigle_dic_class2[key].append(dic2[key][out_index])
            dic1[str(dic2[key][out_index][0])].remove(dic2[key][out_index])
            item=dic2[key][out_index]  # 11.17号新加
            dic2[key].remove(dic2[key][out_index])
            out_index -= 1
        else:
            break
    while out_index2 <= len(dic2[key]) - 1:
        if ((item[0] - dic2[key][out_index2][0]) ** 2 + (item[1] - dic2[key][out_index2][1]) ** 2) ** 0.5 <= n:
            sigle_dic_class2[key].append(dic2[key][out_index2])
            dic1[str(dic2[key][out_index2][0])].remove(dic2[key][out_index2])
            item = dic2[key][out_index2]  # 11.17号新加
            dic2[key].remove(dic2[key][out_index2])
            out_index2 += 1
        else:
            break


def rows(key,out_index,item,dic1,dic2,sigle_dic_class1):
    out_index2 = out_index
    while out_index >= 0:
        if ((item[0] - dic1[key][out_index][0]) ** 2 + (
                item[1] - dic1[key][out_index][1]) ** 2) ** 0.5 <= n:
            sigle_dic_class1[key].append(dic1[key][out_index])
            dic2[str(dic1[key][out_index][1])].remove(dic1[key][out_index])
            item = dic1[key][out_index]  # 11.17号新加
            dic1[key].remove(dic1[key][out_index])
            out_index -= 1
        else:
            break
    while out_index2 <= len(dic1[key]) - 1:
        if ((item[0] - dic1[key][out_index2][0]) ** 2 + (
                item[1] - dic1[key][out_index2][1]) ** 2) ** 0.5 <= n:
            sigle_dic_class1[key].append(dic1[key][out_index2])
            dic2[str(dic1[key][out_index2][1])].remove(dic1[key][out_index2])
            item = dic1[key][out_index2]  # 11.17号新加
            dic1[key].remove(dic1[key][out_index2])
            out_index2 += 1
        else:
            break



#1.通过某个坐标获得该行所有属于该类的坐标得到sigle_dic_class1
#2.从dic1和dic2删除所有已经处理的行的坐标
#3.通过sigle_dic_class1的行坐标获得每个坐标的列的坐标sigle_dic_class2,并将处理过的列坐标从dic1和dic2删除
def row_index_class(classes,dic1,dic2,sigle_dic_class1,sigle_dic_class2,n,key):
    print("...............................某个坐标找到所有符合条件的类................................................")
    print("classes",classes)
    print("dic1", dic1)
    print("dic2", dic2)
    print("sigle_dic_class1", sigle_dic_class1)
    print("sigle_dic_class2", sigle_dic_class2)

    #1.遍历某一行的所有的同类的坐标
    print("....................#1.遍历某一行的所有的同类的坐标.............................")

    if key in dic1:
        while len(dic1[key])>0:
            for item in sigle_dic_class1[key]:

                if dic1[key]==[]:
                    break
                else:

                    list1 = dic1[key]
                    d1 = item
                    i = 1
                    print("?????????????????????",item)
                    print("***********************",dic1[key])
                    out_index = finddata(d1, list1, i)  # 二分法查找该列与该坐标的行坐标相近的坐标
                    rows(key, out_index, item, dic1, dic2, sigle_dic_class1)#找到该行所有的满足该坐标类的坐标,并将其删除
                    break
            break
        if dic1[key]==[]:
            del dic1[key]

    for items in sigle_dic_class1[key]:#如果dic2键的坐标删完了,则删除该键
        if str(items[1]) in dic2:
            if dic2[str(items[1])]==[]:
                del dic2[str(items[1])]
        if items not in classes:
            classes.append(items)

    #2.sigle_dic_class2获得sigle_dic_class1的元素所在同类的列的所有元素
    for item in sigle_dic_class1[key]:
        if str(item[1]) in dic2:
            if dic2[str(item[1])]==[]:#如果dic2的某个键的元素为空,则删除该键
                del dic2[str(item[1])]
            if str(item[1]) in sigle_dic_class2:  # 如果该键的dic1的元素为空,则将sigle_dic_class1的该键的元素加入classes,然后删除该键
                for items in sigle_dic_class2[str(item[1])]:
                    classes.append(items)
                del sigle_dic_class2[str(item[1])]

            else:
                while len(dic2[str(item[1])])>0:
                    list1 = dic2[str(item[1])]
                    d1 = item
                    i = 0
                    out_index = finddata(d1, list1, i)  # 二分法查找该列与该坐标的行坐标相近的坐标
                    row_dic_del(i, out_index, item, list1, classes, dic1, dic2, sigle_dic_class1, sigle_dic_class2)#删除该坐标所在的行和列所满足的元素
                    break
                if dic2[str(item[1])] == []:#如果dic2的某个键的元素为空,则删除该键
                    del dic2[str(item[1])]
                    if str(item[1]) in sigle_dic_class2:  # 如果该键的dic1的元素为空,则将sigle_dic_class1的该键删除
                        del sigle_dic_class2[str(item[1])]

    del sigle_dic_class1[key]#删除sigle_dic_class1的该行

    return classes,dic1,dic2,sigle_dic_class1,sigle_dic_class2


#1.通过某个坐标获得该行所有属于该类的坐标得到sigle_dic_class1
#2.从dic1和dic2删除所有已经处理的行的坐标
#3.通过sigle_dic_class1的行坐标获得每个坐标的列的坐标sigle_dic_class2,并将处理过的列坐标从dic1和dic2删除
def col_index_class(classes,dic1,dic2,sigle_dic_class1,sigle_dic_class2,n,key):

    # 1.遍历某一行的所有的同类的坐标
    print("....................#2.遍历某一行的所有的同类的坐标.............................")
    if key in dic2:
        while len(dic2[key]) > 0:
            for item in sigle_dic_class2[key]:
                if dic2[key] == []:
                    break
                else:
                    while len(dic2[key]) > 0:
                        list1 = dic2[key]
                        d1 = item
                        i = 1
                        out_index = finddata(d1, list1, i)  # 二分法查找该列与该坐标的行坐标相近的坐标
                        cols(key, item, out_index, dic1, dic2, sigle_dic_class2)#找到该行所有的满足该坐标类的坐标,并将其删除
                        break
            break

        if dic2[key] == []:  # 如果dic2键的坐标删完了,则删除该键
            del dic2[key]

    for items in sigle_dic_class2[key]:  # 如果dic1键的坐标删完了,则删除该键
        if str(items[0]) in dic1:
            if dic1[str(items[0])] == []:
                del dic1[str(items[0])]
        if items not in classes:
            classes.append(items)

    # 2.sigle_dic_class2获得sigle_dic_class1的元素所在同类的列的所有元素
    for item in sigle_dic_class2[key]:
        if str(item[0]) in dic1:
            if dic1[str(item[0])]==[]:#如果dic1的某个键的元素为空,则删除该键
                del dic1[str(item[0])]
                if str(item[0]) in sigle_dic_class1:#如果该键的dic1的元素为空,则将sigle_dic_class1的该键的元素加入classes,然后删除该键
                    for items in sigle_dic_class1[str(item[0])]:
                        classes.append(items)
                    del sigle_dic_class1[str(item[0])]
            else:
                while len(dic1[str(item[0])]) > 0:
                    list1=dic1[str(item[0])]
                    d1=item
                    i=1
                    out_index=finddata(d1,list1,i)#二分法查找该列与该坐标的行坐标相近的坐标

                    col_dic_del(i,out_index, item, list1, classes, dic1, dic2, sigle_dic_class1, sigle_dic_class2)#删除该坐标所在的行和列所满足的元素
                    break

                if dic1[str(item[0])]==[]:#如果dic1的某个键的元素为空,则删除该键
                    del dic1[str(item[0])]

                    if str(item[0]) in sigle_dic_class1:#如果该键的dic1的元素为空,则将sigle_dic_class1的该键删除
                        del sigle_dic_class1[str(item[0])]

    del sigle_dic_class2[key]  # 删除sigle_dic_class1的该行

    return classes, dic1, dic2, sigle_dic_class1, sigle_dic_class2


def dic_class(lists,n):

    #1.从lists获得dic1,dic2
    dic1,dic2=dic1_dic2(lists)

    #2.某一个类的新类,获得初始值,且获取这个值后,删除原有类中的元素
    sigle_dic_class1=dic_get_value1(dic1)

    #3.分别遍历sigle_dic_class1, sigle_dic_class2,其中sigle_dic_class1每个键找dic2
    #类存储元素
    classes=[]
    sigle_dic_class2 = {}

    print("......................1111111...........................")
    key_1 = list(sigle_dic_class1.keys())
    classes.append(sigle_dic_class1[key_1[0]][0])
    dic1[key_1[0]].remove(sigle_dic_class1[key_1[0]][0])
    dic2[str(sigle_dic_class1[key_1[0]][0][1])].remove(sigle_dic_class1[key_1[0]][0])
    print(sigle_dic_class1)
    print(classes)
    print("......................1111111...........................")

    # 3.sigle_dic_class1的键是行坐标,对所对应的所有的列dic1进行遍历,查找符合类的坐标

    j = 0
    i=0
    while len(sigle_dic_class1)>0 or len(sigle_dic_class2)>0:
        while len(sigle_dic_class1) > 0:
            print("///:", j)
            j += 1
            key_1 = list(sigle_dic_class1.keys())
            if sigle_dic_class1[key_1[0]][0] not in classes:
                classes.append(sigle_dic_class1[key_1[0]][0])
            classes, dic1, dic2, sigle_dic_class1, sigle_dic_class2 = row_index_class(classes, dic1, dic2, sigle_dic_class1,
                                                                                      sigle_dic_class2, n, key_1[0])
            print("dic1", dic1)
            print("dic2", dic2)
            print("sigle_dic_class2", sigle_dic_class2)
            print("sigle_dic_class1", sigle_dic_class1)
            print("classes", classes)

        # 4.sigle_dic_class2的键是列坐标,对所对应的所有的列dic2进行遍历,查找符合类的坐标
        while len(sigle_dic_class2) > 0:
            print("======>", i)
            i += 1
            key_2 = list(sigle_dic_class2.keys())
            if sigle_dic_class2[key_2[0]][0] not in classes:
                classes.append(sigle_dic_class2[key_2[0]][0])
            classes, dic1, dic2, sigle_dic_class1, sigle_dic_class2 = col_index_class(classes, dic1, dic2, sigle_dic_class1,
                                                                                      sigle_dic_class2, n, key_2[0])
            print(
                ".........................................................................................................................................")
            print("dic1", dic1)
            print("dic2", dic2)
            print("sigle_dic_class2", sigle_dic_class2)
            print("sigle_dic_class1", sigle_dic_class1)
            print("classes", classes)
            print(len(classes))

    return classes



if __name__ == '__main__':
    data = [
        [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0],
        [1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
        [1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0],
        [1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0],
        [0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0],
        [0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0],
        [0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0],
        [0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0],
    ]

    data1 = [
        [0, 0, 0, 1, 1, 0, 0],  # 1
        [0, 1, 1, 1, 1, 1, 0],  # 2
        [0, 1, 1, 1, 1, 1, 0],  # 3
        [1, 1, 1, 1, 1, 1, 1],  # 4
        [0, 1, 1, 1, 1, 1, 0],  # 5
        [0, 1, 1, 1, 1, 1, 0],  # 6
        [0, 0, 0, 1, 0, 0, 0]]  # 7

    # 1.数据处理,将数据处理为二维数组=======>[(0, 3), (1, 1), (1, 2),........, (1, 3), (1, 4), (1, 5)]
    lists = data_set(data)
    print("......................list.......................")
    print("1.list:", lists)

    # DBSCAN算法中某一个类的拟合
    n = 3

    classes = dic_class(lists, n)
    print(len(lists),len(classes))
    for i in range(len(data)):
        for j in range(len(data[0])):
            if (i, j) in classes:
                data[i][j] = 2
    data = np.array(data)
    print(data)

你可能感兴趣的:(机器学习,python,人工智能)