def TraMapSag(sagPoints,traPath): r1, c1, o1, pixelSpacingXY, n1 = sagPoints orienta, pos, pixelSpa = dicom_metainfo(traPath, ['0020|0037', '0020|0032', '0028|0030']) (r2, c2), o2, pixelSpa = parse_orentation(orienta), parse_position(pos), parse_pixelSpacing( pixelSpa) image = dicom2array(traPath) srcHeigh, srcWidth = image.shape[:2] p1 = o2 # 左上角的点 p2 = p1 + r2 * pixelSpa[0] * (srcWidth - 1) # 右上角的点 p3 = p2 + c2 * pixelSpa[1] * (srcHeigh - 1) # 右下角的点 p4 = p1 + c2 * pixelSpa[1] * (srcHeigh - 1) # 左下角的点 # 点到平面的距离 # p1 O1 dv1 = np.dot(p1 - o1, n1) # p2 O1 dv2 = np.dot(p2 - o1, n1) # p3 O1 dv3 = np.dot(p3 - o1, n1) # p4 O1 dv4 = np.dot(p4 - o1, n1) iscross12 = ((dv1 > 0) & (dv2 < 0)) | ((dv1 < 0) & (dv2 > 0)) iscross23 = ((dv2 > 0) & (dv3 < 0)) | ((dv2 < 0) & (dv3 > 0)) iscross34 = ((dv3 > 0) & (dv4 < 0)) | ((dv3 < 0) & (dv4 > 0)) iscross41 = ((dv4 > 0) & (dv1 < 0)) | ((dv4 < 0) & (dv1 > 0)) if not (iscross12 | iscross23 | iscross34 | iscross41): return cps = [] for iscross, (pv, pp), (ddv, ddp) in zip([iscross12, iscross23, iscross34, iscross41], [(p1, p2), (p2, p3), (p3, p4), (p4, p1)], [(dv1, dv2), (dv2, dv3), (dv3, dv4), (dv4, dv1)]): if not iscross: # 是否相交 continue # 计算交点坐标 相似三角形? cp = [pv[i] + (pp[i] - pv[i]) * ddv / (ddv - ddp) for i in range(3)] cps.append(np.array(cp)) # for cp in cps: # # 看下算出来的点在不在定位图平面上 带入平面方程 正确应该是几乎等于0 # print(n1 * (cp - o1)) assert len(cps) == 2 coords = [] coords_img = [] for cp in cps: # 投影 xmap = np.dot(cp - o1, r1) / np.linalg.norm(r1) ymap = np.dot(cp - o1, c1) / np.linalg.norm(c1) # 这个没什么用 coords.append(np.array(xmap, ymap)) # pixel坐标 coords_img.append(np.array([int(xmap / pixelSpacingXY[0]), int(ymap / pixelSpacingXY[1])])) #得到映射到sag的两个点 return coords_img
def SagKeyPoints(sagPath): image1 = dicom2array(sagPath) orienta, pos, pixelSpacingXY = dicom_metainfo(sagPath, ['0020|0037', '0020|0032', '0028|0030']) (r1, c1), o1, pixelSpacingXY = parse_orentation(orienta), parse_position(pos), parse_pixelSpacing( pixelSpacingXY) srcHeigh, srcWidth = image1.shape[:2] n1 = np.cross(r1, c1) p1 = o1 # 左上角的点 p2 = p1 + r1 * pixelSpacingXY[0] * (srcWidth - 1) # 右上角的点 p3 = p2 + c1 * pixelSpacingXY[1] * (srcHeigh - 1) # 右下角的点 p4 = p1 + c1 * pixelSpacingXY[1] * (srcHeigh - 1) # 左下角的点 return r1,c1,o1,pixelSpacingXY,n1
def metricDetect(yolo, truejson, testFile, sliceResize): with open(truejson, "r", encoding="utf-8") as f: truejsonTarge = json.loads(f.read()) from classifycation import CNN cnn_disc = CNN(sliceResize) model_disc = cnn_disc.loadTestdisc() cnn_discv5 = CNN(sliceResize) model_discv5 = cnn_discv5.loadTestdiscv5() cnn_vertebra = CNN(sliceResize) model_vertebra = cnn_vertebra.loadTestvertebra() TruePointNum = 0 TP = 0 #在目标内且 如果分类正确 FP = 0 #在目标内且 分类错误 and 如果预测的点不落在任何标注点 FN = 0 #标注点没有被任何预测点正确命中 vertebraTP = 0 vertebraFP = 0 discTP = 0 discFP = 0 mm6c = 0 mmc = 0 count = 0 study = os.listdir(testFile) for studyI in study: Impath = os.listdir(os.path.join(testFile, studyI)) for Impathi in Impath: try: studyUid, seriesUid, instanceUid = dicom_metainfo( os.path.join(os.path.join(testFile, studyI), Impathi), ['0020|000d', '0020|000e', '0008|0018']) for studyid in truejsonTarge: if studyUid == studyid["studyUid"] and seriesUid == studyid[ "data"][0]["seriesUid"] and instanceUid == studyid[ "data"][0]["instanceUid"]: count += 1 image = dicom2array( os.path.join(os.path.join(testFile, studyI), Impathi)) truepoints = studyid["data"][0]["annotation"][0][ "data"]["point"] image = Image.fromarray(image) image = image.convert("RGB") r_image, points = yolo.detect_image(image) #判断检测点与真实点 mean = np.mean(image) std = np.mean(np.square(image - mean)) image = (image - mean) / np.sqrt(std) image = np.asarray(image) m, n, _ = image.shape matchedIndex = [] for truepoint in truepoints: mmc += 1 xt, yt = list(map(int, truepoint["coord"])) tag = truepoint["tag"] if "disc" in tag.keys(): ct = tag["disc"] else: ct = tag["vertebra"] xy = sorted(points, key=lambda x: x[2]) deta = [] for i in range(len(xy) - 1): deta.append(xy[i + 1][2] - xy[i][2]) deta = np.mean(deta) print("deta:", deta) for index, metricpoint in enumerate(points): c, x, y = metricpoint mm = 6 mm8 = 8 if x <= xt + mm and x >= xt - mm and y <= yt + mm and y >= yt - mm: # 在标注点内 matchedIndex.append(index) mm6c += 1 TruePointNum += 1 w1, h1 = m / 5, n / 20 # 椎间盘要求更长而不是更高 n控制高度 offset = 5 miny = y - deta maxy = y + deta minx = x + offset - w1 / 2 maxx = x + offset + w1 / 2 # nimg_x = image[int(miny):int(maxy), int(minx):int(maxx)] if "disc" in tag.keys(): xlen2 = int(w1 / 2) X = dealImg(image, int(miny), int(maxy), int(minx) + int(xlen2), int(maxx), sliceResize) X = X.reshape([1] + sliceResize + [1]) p = model_disc.predict(X) pre = np.argmax(p, axis=1) pc = cnn_disc.disc_label[int(pre)] if pc == ct: TP += 1 discTP += 1 else: FP += 1 discFP += 1 else: w1, h1 = m / 5, n / 20 # 识别框的宽度和高度 更大 offset = 0 miny = y - h1 #- deta - offset maxy = y + h1 #+ deta + offset minx = x + offset - w1 / 2 maxx = x + offset + w1 / 2 # nimg_x = image[int(miny):int(maxy), int(minx):int(maxx)] # nimg_x = cv2.resize(nimg_x, (sliceResize[1], sliceResize[0]))[:, :, 1] X = dealImg(image, int(miny), int(maxy), int(minx), int(maxx), sliceResize) # plt.subplot(4, 5, int(1 + 5 * 1)) # plt.imshow(X[:,:,0]) # plt.show() X = X.reshape([1] + sliceResize + [1]) p = model_vertebra.predict(X) pre = np.argmax(p, axis=1) pc = cnn_vertebra.vertebra_label[int( pre)] if pc == ct: TP += 1 vertebraTP += 1 else: FP += 1 vertebraFP += 1 break FP += len(points) - len(matchedIndex) except: print("文件错误:", os.path.join(os.path.join(dataPath, studyI), Impathi)) print("总共点数:", mmc) print("TP/总定位:", TruePointNum / mmc, "TP/(TP+FP):", TP / (TP + FP + 1e-2)) print("discTP/(TP+FP):", discTP / (discTP + discFP), "vertebraTP/(TP+FP):", vertebraTP / (vertebraTP + vertebraFP))
def step1(dataPath, jsondata, truejsonPath=None): ''' 将 图片 与 锚点对应 :return: ''' image = {} count = 0 study = os.listdir(dataPath) for studyI in study: Impath = os.listdir(os.path.join(dataPath, studyI)) # print("study:", studyI) for Impathi in Impath: try: studyUid, seriesUid, instanceUid, desc, idex = dicom_metainfo( os.path.join(os.path.join(dataPath, studyI), Impathi), [ '0020|000d', '0020|000e', '0008|0018', '0008|103e', "0020|0013" ]) for studyid in jsondata: if studyUid == studyid["studyUid"] and seriesUid == studyid[ "data"][0]["seriesUid"] and instanceUid == studyid[ "data"][0]["instanceUid"]: count += 1 image[studyI + "_" + Impathi] = dicom2array( os.path.join(os.path.join(dataPath, studyI), Impathi)) # 在yolo.py中运行watchTest打开注释 img = dicom2array( os.path.join(os.path.join(dataPath, studyI), Impathi)) # if studyI == seestudy: plt.figure() plt.title(studyI + "_" + Impathi + "\t" + desc + '\t' + idex) plt.imshow(img) if truejsonPath != None: for studyid1 in truejsonPath: if studyUid == studyid1[ "studyUid"] and seriesUid == studyid1[ "data"][0][ "seriesUid"] and instanceUid == studyid1[ "data"][0]["instanceUid"]: truePoints = studyid1["data"][0][ "annotation"][0]["data"]["point"] for point in truePoints: x, y = point['coord'] print("True zIndex:", point["zIndex"]) tag = point['tag'] loc = tag['identification'] if "disc" in tag.keys(): k = tag["disc"] else: k = tag["vertebra"] # if studyI == seestudy: plt.scatter(x, y, s=12, c='g') plt.text(x=x + 5, y=y - 5, s=loc + '**' + k) for point in studyid["data"][0]["annotation"][0][ "data"]["point"]: x, y = point['coord'] # print("zIndex:",point["zIndex"] ," red") tag = point['tag'] loc = tag['identification'] if "disc" in tag.keys(): k = tag["disc"] else: k = tag["vertebra"] # if studyI == seestudy: plt.scatter(x, y, s=6, c='r') plt.text(x=x + 5, y=y, s=loc + '--' + k) # if studyI == seestudy: plt.show() except: print("文件错误:", os.path.join(os.path.join(dataPath, studyI), Impathi))
def step1Test(dataPath,testTxt=None): ''' 在准备jpg时,首先先判断是否为T2_sag,只对T2_sag做定位识别 target: t2sag:0, t1sag:1, t2tra:2 :param dataPath: :return: ''' count = 0 study = os.listdir(dataPath) f = open(testTxt, 'r') datas = f.readlines() f.close() for data in datas: d = data.split() ImgPath = d[0].split('/')[-1].split('.')[0].split('_') # 寻找dcm studyI = ImgPath[0] dicmPath = dataPath + '/' + ImgPath[0] + "/" + ImgPath[1] + '.dcm' #answer中间帧 Impath = os.listdir(os.path.join(dataPath, studyI)) #找到study下的所有dcm 为了寻找tra,同一标签下第一左边方差小 describes2pos = {} describes2imgPathes = {} for Impathi in Impath: pos = dicom_metainfo(os.path.join(os.path.join(dataPath, studyI), Impathi), ['0020|0032'])[0] describ = dicom_metainfo(os.path.join(os.path.join(dataPath, studyI), Impathi), ['0008|103e'])[0] seriesNumber = dicom_metainfo(os.path.join(os.path.join(dataPath, studyI), Impathi), ['0020|0011'])[0] describ += seriesNumber if re.match(r"(.*)[sS][cC][oO][uU][tT](.*)", describ, 0): #不加入 continue elif re.match(r"(.*)[sS][aA][gG](.*)",describ,flags=0) or re.match(r"(.*)[sS][aA][gG](.*)",describ,0): continue else: if describ not in describes2pos.keys(): describes2pos[describ] = [parse_position(pos)[0]] describes2imgPathes[describ] = [Impathi] else: describes2pos[describ].append(parse_position(pos)[0]) describes2imgPathes[describ].append(Impathi) describes2posN = {} describes2imgPathesN = {} flagN = False for key, value in describes2pos.items(): if re.match(r"(.*)[tT][rR][aA](.*)",key,flags=0): flagN = True describes2posN[key] = value describes2imgPathesN[key] = describes2imgPathes[key] if flagN: describes2pos = describes2posN describes2imgPathes = describes2imgPathesN plt.figure(1) imgSAG = dicom2array(dicmPath) plt.imshow(imgSAG) sagPoints = SagKeyPoints(dicmPath) index = 0 for key,value in describes2pos.items(): if np.std(np.array(value))<10 and len(value) > 6: # plt.figure(2) print("找到tra! -- ",studyI,key," -- ",len(value)) count += 1 clusData = [] for traPath in describes2imgPathes[key]: traDim = os.path.join(os.path.join(dataPath, studyI), traPath) TraMapSagPoints = TraMapSag(sagPoints,traDim) imgTRA = dicom2array(traDim) # plt.subplot(2,int(len(value)/2)+1,index+1) # plt.imshow(imgTRA) plt.plot((TraMapSagPoints[0][0], TraMapSagPoints[1][0]), (TraMapSagPoints[0][1], TraMapSagPoints[1][1])) x1,x2 = int(TraMapSagPoints[0][0]),int(TraMapSagPoints[1][0]) y1,y2 = int(TraMapSagPoints[0][1]),int(TraMapSagPoints[1][1]) clusData.append([y1,y2,x1,x2, traDim]) plt.plot(x1, y1, "o", color='red', ms=10) plt.plot(x2, y2, "o", color='g', ms=10) plt.plot(int((x1+x2)/2), int((y1+y2)/2), "o", color='g', ms=10) plt.text(x1, y1,str(index)) index += 1 thresh = 30 print(sorted(clusData,key=lambda x:x[0])) clusData = sorted(clusData, key=lambda x: x[0]) clusDataN = [[i[0]] for i in clusData] traDimN = [i[-1] for i in clusData] clusters = hcluster.fclusterdata(np.array(clusDataN), thresh, criterion="distance") print(clusters,set(clusters.tolist())) clustersDic = dealCluster(clusters,clusData) print(clustersDic) d = sortPoint(d) for index, target in enumerate(d): x, y, vd, c, p = target.split(',') if vd == "disc": print("==") flag,dicm = xyIndcm(int(x),int(y),clustersDic) if flag: print(dicm) plt.plot(int(x), int(y), "o", color='r', ms=5) plt.show() print(count)