diff --git a/GetAnnFromXml.py b/GetAnnFromXml.py index caab0bb..ad7e5ba 100644 --- a/GetAnnFromXml.py +++ b/GetAnnFromXml.py @@ -1,10 +1,9 @@ +""" +This program is used for read an annotation xml File and store in class Annotation +""" import xml.etree.cElementTree as ET import os.path import math -""" -This program is used for read an annotation part and store in class Annotation -border = [0,0,0,0] #A 4 - index list [leftmost, rightmost, upmost, downmost] -""" class Annotation(object): def __init__(self): self.name = " " @@ -18,7 +17,12 @@ def __init__(self): self.yMin = 0 self.yMax = 0 -class getAnnFromXml(object): + # Use for record which patch is in the annotation + self.patchInAnn = {} + # patch size + self.patchSize = 50 + +class GetAnnFromXml(object): def __init__(self, fileName): self.tree = ET.ElementTree(file = fileName) self.annList = [] diff --git a/GetPatchInAnn.py b/GetPatchInAnn.py new file mode 100644 index 0000000..77eb0a5 --- /dev/null +++ b/GetPatchInAnn.py @@ -0,0 +1,52 @@ +""" +This program is used to store patches which have all their 4 angles' coordinates are in the annotation Anngon +""" +import sys +sys.path.append("../IsPointInAnn") +from IsPointInAnn import point, isPointInAnn +import openslide +from openslide import open_slide # http://openslide.org/api/python/ +from PIL import Image + +class GetPatchInAnn(object): + def __init__(self, currentAnn) : + self.ann = currentAnn + self.annPointGroup = [] + self.pointInAnn = {} + + def getPatch(self): + self.groupXY() + self.checkPointsInAnn() + self.checkPatchInAnn() + + def groupXY(self): + for i in range(0, len(self.ann.coordinateX)): + self.annPointGroup.append(point(float(self.ann.coordinateX[i]), float(self.ann.coordinateY[i]))) + self.annPointGroup.append(self.annPointGroup[0]) + + # Find out if each point is in the Annotation, and tag True if it is, tag False if it is not + def checkPointsInAnn(self): + for i in range(self.ann.xMin, self.ann.xMax, self.ann.patchSize): + for j in range(self.ann.yMin, self.ann.yMax, self.ann.patchSize): + if isPointInAnn().isInAnn(point(i, j), self.annPointGroup): + self.pointInAnn.update({(i, j) : True}) + else: + self.pointInAnn.update({(i, j) : False}) + + #Find out if a patch is in annotation, and tag True if it is, tag False if it is not + def checkPatchInAnn(self): + for i in range(self.ann.xMin, self.ann.xMax, self.ann.patchSize): + for j in range(self.ann.yMin, self.ann.yMax, self.ann.patchSize): + if self.isFourAnglesInAnn(i, j): + self.ann.patchInAnn.update({(i, j) : True}) + else: + self.ann.patchInAnn.update({(i, j) : False}) + + def isFourAnglesInAnn(self, i, j): + inAnn = False + if self.pointInAnn.get((i, j))\ + and self.pointInAnn.get((i + self.ann.patchSize, j))\ + and self.pointInAnn.get((i , j + self.ann.patchSize))\ + and self.pointInAnn.get((i + self.ann.patchSize, j + self.ann.patchSize)): + inAnn = True + return inAnn diff --git a/IsPointInAnn.py b/IsPointInAnn.py index d8a8055..23053c8 100644 --- a/IsPointInAnn.py +++ b/IsPointInAnn.py @@ -16,10 +16,13 @@ def __init__(self): def isInAnn(self, testPoint, annPointGroup): inAnn = False for i in range(0, len(annPointGroup) - 1): + # If there are odd number of lines line in the left of the points, + # then the point is in in the annotation if (self.pointLieRight(testPoint, annPointGroup[i], annPointGroup[i+1])): inAnn = not inAnn return inAnn + # Check if the point is lying right of the line(annPoint1 - annPoint2) def pointLieRight(self, testPoint, annPoint1, annPoint2): lieRight = False if min(annPoint1.y, annPoint2.y) < testPoint.y <= max(annPoint1.y, annPoint2.y)\ diff --git a/PlotPatchInAnn.py b/PlotPatchInAnn.py new file mode 100644 index 0000000..336d17a --- /dev/null +++ b/PlotPatchInAnn.py @@ -0,0 +1,34 @@ +""" +Draw the graph that include the annotation part and patches part +""" +import matplotlib.pyplot as plt + +class PlotPatchInAnn(object): + def __init__(self, currentAnn): + self.annImg = plt.subplot(111) + self.ann = currentAnn + + def plotPatch(self): + self.addAnnGraph() + for i in range(self.ann.xMin, self.ann.xMax, self.ann.patchSize): + for j in range(self.ann.yMin, self.ann.yMax, self.ann.patchSize): + if self.ann.patchInAnn.get((i, j)): + self.addPatchGraph(i, j) + self.showAnnGraph() + + def addAnnGraph(self): + AnnPoints = [] + for i in range(0, len(self.ann.coordinateX)): + AnnPoints.append((self.ann.coordinateX[i], self.ann.coordinateY[i])) + AnnGraph = plt.Polygon(AnnPoints, fill = None, edgecolor = 'r') + self.annImg.add_patch(AnnGraph) + + def addPatchGraph(self, i, j): + print (i, j) + patchPoints = [(i,j), (i + self.ann.patchSize, j), (i + self.ann.patchSize, j + self.ann.patchSize), (i, j + self.ann.patchSize)] + patch = plt.Polygon(patchPoints, fill = None, edgecolor = 'b') + self.annImg.add_patch(patch) + + def showAnnGraph (self): + self.annImg.plot() + plt.show() diff --git a/SavePatchInAnn.py b/SavePatchInAnn.py new file mode 100644 index 0000000..fdc7464 --- /dev/null +++ b/SavePatchInAnn.py @@ -0,0 +1,22 @@ + +dirFolder = r'C:\Users\nctu\Desktop\ScanAnnotation\inAnn' + +class SavePatchInAnn(object): + def __init__(self, scan, currentAnn, currentSaveIndex): + self.scan = scan + self.ann = currentAnn + self.saveIndex = currentSaveIndex + + def savePatch(self): + for i in range(self.ann.xMin, self.ann.xMax, self.ann.patchSize): + for j in range(self.ann.yMin, self.ann.yMax, self.ann.patchSize): + if self.ann.patchInAnn.get((i, j)): + self.savePatchFromSlide(i, j) + + def savePatchFromSlide(self, i, j): + img = self.scan.read_region((i,j), 0 , (self.ann.patchSize, self.ann.patchSize)) + img.save(str(dirFolder)+ '\\' + str(self.saveIndex) + ".png") + self.saveIndex += 1 + + def updateSaveIndex(self): + return self.saveIndex diff --git a/ScanAnnotations.py b/ScanAnnotations.py index e236643..ca487cc 100644 --- a/ScanAnnotations.py +++ b/ScanAnnotations.py @@ -1,24 +1,43 @@ import sys -sys.path.append("../CutAnnToPatches") sys.path.append("../GetAnnFromXml") -from CutAnnToPatches import cutAnnToPatches -from GetAnnFromXml import getAnnFromXml +sys.path.append("../GetPatchInAnn") +sys.path.append("../SavePatchInAnn") +sys.path.append("../PlotPatchInAnn") +from GetAnnFromXml import GetAnnFromXml +from GetPatchInAnn import GetPatchInAnn +from SavePatchInAnn import SavePatchInAnn +from PlotPatchInAnn import PlotPatchInAnn import openslide from openslide import open_slide # http://openslide.org/api/python/ sysFilePath = r'C:\Users\nctu\Desktop\svs_scanner\svs_image\patient_004_node_4.tif' xmlFilePath = "patient_004_node_4.xml" -class scanAnnotations(object): +class ScanAnnotations(object): def __init__(self, sysFilePath, xmlFilePath): - getAnn = getAnnFromXml(xmlFilePath) + getAnn = GetAnnFromXml(xmlFilePath) self.annList = getAnn.readXml() self.scan = openslide.OpenSlide(sysFilePath) + self.currentSaveIndex = 0 def scanAnnotations(self): for currentAnn in self.annList: - ann = cutAnnToPatches( self.scan, currentAnn) - ann.cutAnn() + self.getPatchInAnnotation(currentAnn) + self.savePatchInAnnotation(self.scan, currentAnn, self.currentSaveIndex) + self.plotPatchInAnnotation(currentAnn) -test = scanAnnotations(sysFilePath, xmlFilePath) + def getPatchInAnnotation(self, ann): + annGet = GetPatchInAnn(ann) + annGet.getPatch() + + def savePatchInAnnotation(self, scan, ann, saveIndex): + annSave = SavePatchInAnn(scan, ann, saveIndex) + annSave.savePatch() + self.currentSaveIndex = annSave.updateSaveIndex() + + def plotPatchInAnnotation(self, ann): + annShow = PlotPatchInAnn(ann) + annShow.plotPatch() + +test = ScanAnnotations(sysFilePath, xmlFilePath) test.scanAnnotations()