Commit 40f9393a authored by Josef Brandt's avatar Josef Brandt

Global scale factor for image in segmentation

parent e9854f67
......@@ -178,13 +178,6 @@ class ImageView(QtWidgets.QLabel):
self.drag = "add"
p0 = event.pos()
self.appendSeedPoints(p0)
# print(p0)
# if self.drag =="add":
# self.seedpoints.append([p0.x(), p0.y(), self.seedradius])
# elif self.drag =="delete":
# self.seeddeletepoints.append([p0.x(), p0.y(), self.seedradius])
# elif self.drag == "remove":
# self.removeSeeds([p0.x(), p0.y()])
self.update()
super().mousePressEvent(event)
......@@ -193,12 +186,6 @@ class ImageView(QtWidgets.QLabel):
if self.drag:
p0 = event.pos()
self.appendSeedPoints(p0)
# if self.drag == "add":
# self.seedpoints.append([p0.x(),p0.y(),self.seedradius])
# elif self.drag == "delete":
# self.seeddeletepoints.append([p0.x(),p0.y(),self.seedradius])
# else:
# self.removeSeeds([p0.x(),p0.y()])
self.update()
super().mouseMoveEvent(event)
......@@ -318,13 +305,31 @@ class ParticleDetectionView(QtWidgets.QWidget):
self.showseedpoints.setChecked(True)
self.setImageCenter()
self.globalScaleFactor = QtWidgets.QDoubleSpinBox(self)
self.globalScaleLabel = QtWidgets.QLabel('')
self.globalScaleFactor.valueChanged.connect(self.updatePixelScaleLabel)
self.globalScaleFactor.setMinimum(0.01)
self.globalScaleFactor.setMaximum(1.)
self.globalScaleFactor.setSingleStep(0.1)
self.globalScaleFactor.setDecimals(2)
self.globalScaleFactor.setValue(1.)
self.globalScaleFactor.valueChanged.connect(self.autoUpdateIfDesired)
globalScaleValueFunc = makeValueLambda(self.globalScaleFactor.value)
self.detectParamsGroup = QtWidgets.QGroupBox("Detection settings", self)
grid = QtWidgets.QGridLayout()
self.parameters = []
self.parameters.append([self.globalScaleFactor, 'globalScaleFactor', globalScaleValueFunc, None])
checkBoxesToLink = {}
grid.addWidget(self.globalScaleLabel, 0, 0, QtCore.Qt.AlignLeft)
grid.addWidget(self.globalScaleFactor, 0, 1, QtCore.Qt.AlignRight)
# create editable parameters:
for i, p in enumerate(self.seg.parlist):
i += 1
label, colstretch = None, 1
if p.name == "contrastCurve":
paramui = HistWidget(lambda : self.seg.calculateHist(self.seg.convert2Gray(self.subimg)),
......@@ -392,8 +397,6 @@ class ParticleDetectionView(QtWidgets.QWidget):
box.stateChanged.connect(makeEnableLambda(box, p[3]))
p[3].setEnabled(box.isChecked())
label = QtWidgets.QLabel("Seed radius", self)
grid.addWidget(label, i+1, 0, QtCore.Qt.AlignLeft)
grid.addWidget(self.seedradiusedit, i+1, 1, QtCore.Qt.AlignLeft)
......@@ -445,6 +448,11 @@ class ParticleDetectionView(QtWidgets.QWidget):
self.setLayout(hbox)
self.setWindowTitle("Particle Detection")
def updatePixelScaleLabel(self):
newScale = self.dataset.getPixelScale(self.dataset.imagescanMode) / self.globalScaleFactor.value()
newScale = np.round(newScale, 2)
self.globalScaleLabel.setText(f'Scale for image (PixelScale: {newScale} µm/px)')
def saveDetectParams(self, ds=None):
if ds is not None:
for param in self.parameters:
......@@ -784,11 +792,12 @@ class ParticleDetectionView(QtWidgets.QWidget):
particleContainer.clearMeasurements()
for particleIndex, measPoints in enumerate(measurementPoints):
for index, point in enumerate(measPoints):
curParticle = particleContainer.getParticleOfIndex(particleIndex)
indexOfNewMeas = particleContainer.addEmptyMeasurement()
particleContainer.setMeasurementPixelCoords(indexOfNewMeas, point.x, point.y)
curParticle.addMeasurement(particleContainer.measurements[indexOfNewMeas])
if len(measPoints) > 0:
for index, point in enumerate(measPoints):
curParticle = particleContainer.getParticleOfIndex(particleIndex)
indexOfNewMeas = particleContainer.addEmptyMeasurement()
particleContainer.setMeasurementPixelCoords(indexOfNewMeas, point.x, point.y)
curParticle.addMeasurement(particleContainer.measurements[indexOfNewMeas])
self.dataset.particleDetectionDone = True
self.dataset.mode = "prepareraman"
......@@ -802,7 +811,7 @@ class ParticleDetectionView(QtWidgets.QWidget):
try:
stats = getParticleStatsWithPixelScale(contour, self.dataset, fullimage=self.img, zimg=zvalimg)
except InvalidParticleError:
print('invalid contour in detection, skipping particle. Contour is:', contour)
print('Invalid contour in detection, skipping particle.')
invalidParticleIndices.append(contourIndex)
continue
particlestats.append(stats)
......
......@@ -112,10 +112,10 @@ class Segmentation(QtCore.QObject):
Parameter("activateUpThresh", np.bool, self.detectParams['activateUpThresh'], helptext="activate upper threshold", show=False, linkedParameter='upThresh'),
Parameter("upThresh", float, self.detectParams['upThresh'], .01, 1.0, 2, .02, helptext="Upper threshold", show=False),
Parameter("maxholebrightness", float, self.detectParams['maxholebrightness'], 0, 1, 2, 0.02, helptext="Close holes brighter than..", show = True),
Parameter("minparticlesize", int, self.detectParams['minparticlesize'], 1, 1000, 0, 50, helptext="Min. particle size (µm)", show=False),
Parameter("minparticlesize", int, self.detectParams['minparticlesize'], 1, 1000, 0, 1, helptext="Min. particle size (µm)", show=False),
Parameter("enableMaxArea", np.bool, self.detectParams['enableMaxArea'], helptext="enable filtering for maximal particle size", show=False, linkedParameter='maxparticlearea'),
Parameter("maxparticlesize", int, self.detectParams['maxparticlesize'], 10, 1E9, 0, 50, helptext="Max. particle size (µm)", show=False),
Parameter("minparticledistance", int, self.detectParams['minparticledistance'], 5, 1000, 0, 5, helptext="Min. distance between particles", show=False),
Parameter("minparticledistance", int, self.detectParams['minparticledistance'], 1, 1000, 0, 5, helptext="Min. distance between particles (µm)", show=False),
Parameter("measurefrac", float, self.detectParams['measurefrac'], 0, 1, 2, stepsize = 0.05, helptext="measure fraction of particles", show=False),
Parameter("closeBackground", np.bool, self.detectParams['closeBackground'], helptext="close holes in sure background", show=False),
Parameter("fuzzycluster", np.bool, self.detectParams['fuzzycluster'], helptext='Enable Fuzzy Clustering', show=False),
......@@ -147,6 +147,10 @@ class Segmentation(QtCore.QObject):
t0 = time()
self.detectionState.emit('DO: setup')
if self.globalScaleFactor != 1.:
img = cv2.resize(img, None, fx=self.globalScaleFactor, fy=self.globalScaleFactor)
print('globalScaleFac = ', self.globalScaleFactor)
gray = self.convert2Gray(img)
self.detectionState.emit('finished GrayScale')
print("gray")
......@@ -228,10 +232,12 @@ class Segmentation(QtCore.QObject):
self.detectionState.emit('finished thresholding')
# modify thresh with seedpoints and deletepoints
for p in np.int32(seedpoints):
cv2.circle(thresh, tuple([p[0], p[1]]), int(p[2]), 255, -1)
for p in np.int32(seedpoints):#
x, y, radius = self.getXYRadiusFromSeedPoint(p, self.globalScaleFactor)
cv2.circle(thresh, (x, y), radius, 255, -1)
for p in np.int32(deletepoints):
cv2.circle(thresh, tuple([p[0], p[1]]), int(p[2]), 0, -1)
x, y, radius = self.getXYRadiusFromSeedPoint(p, self.globalScaleFactor)
cv2.circle(thresh, (x, y), radius, 0, -1)
if return_step=='maxholebrightness': return thresh, 0
if self.cancelcomputation:
......@@ -269,14 +275,19 @@ class Segmentation(QtCore.QObject):
subthresh = np.uint8(255 * (labels[up:(up+height), left:(left+width)] == label))
compMinArea, compMaxArea = minArea, maxArea
scaleFactor = 1.0
if width > self.maxComponentSize or height > self.maxComponentSize:
scaleFactor = max([width/self.maxComponentSize, height/self.maxComponentSize])
subthresh = cv2.resize(subthresh, None, fx=1/scaleFactor, fy=1/scaleFactor)
scaleFactor = 1/max([width/self.maxComponentSize, height/self.maxComponentSize])
subthresh = cv2.resize(subthresh, None, fx=scaleFactor, fy=scaleFactor)
compMinArea *= scaleFactor
compMaxArea *= scaleFactor
subdist = cv2.distanceTransform(subthresh, cv2.DIST_L2, 3)
minDistance = round(self.minparticledistance / scaleFactor)
pixelScale = self.getPixelScaleWithComponentScaleFactor(dataset, scaleFactor)
minDistance = round(self.minparticledistance / pixelScale) #converted from µm into px
sure_fg = self.getSureForeground(subthresh, subdist, minDistance)
sure_bg = cv2.dilate(subthresh, np.ones((5, 5)), iterations = 1)
if self.closeBackground:
......@@ -284,15 +295,11 @@ class Segmentation(QtCore.QObject):
# modify sure_fg and sure_bg with seedpoints and deletepoints
for p in np.int32(seedpoints):
x = int(round(p[0] / scaleFactor)-left)
y = int(round(p[1] / scaleFactor) - up)
radius = int(round(p[2] / scaleFactor))
x, y, radius = self.getXYRadiusFromSeedPoint(p, self.globalScaleFactor*scaleFactor, left, up)
cv2.circle(sure_fg, (x, y), radius, 1, -1)
cv2.circle(sure_bg, (x, y), radius, 1, -1)
for p in np.int32(deletepoints):
x = int(round(p[0] / scaleFactor) - left)
y = int(round(p[1] / scaleFactor) - up)
radius = int(round(p[2] / scaleFactor))
x, y, radius = self.getXYRadiusFromSeedPoint(p, self.globalScaleFactor*scaleFactor, left, up)
cv2.circle(sure_fg, (x, y), radius, 1, -1)
cv2.circle(sure_bg, (x, y), radius, 1, -1)
......@@ -333,32 +340,31 @@ class Segmentation(QtCore.QObject):
tmpcontours = [contours[i] for i in range(len(contours)) if hierarchy[0,i,3]<0]
left = int(round(left / self.globalScaleFactor))
up = int(round(up / self.globalScaleFactor))
for cnt in tmpcontours:
contourArea = cv2.contourArea(cnt) * scaleFactor**2
if minArea <= contourArea <= maxArea:
contourArea = cv2.contourArea(cnt) / (scaleFactor*self.globalScaleFactor)**2
if compMinArea <= contourArea <= compMaxArea:
tmplabel = markers[cnt[0,0,1],cnt[0,0,0]]
if tmplabel ==0:
continue
x0, x1 = cnt[:,0,0].min(), cnt[:,0,0].max()
y0, y1 = cnt[:,0,1].min(), cnt[:,0,1].max()
subimg = (markers[y0:y1+1,x0:x1+1]).copy()
subimg[subimg!=tmplabel ] = 0
subimg[subimg!=tmplabel] = 0
y, x = self.getMeasurementPoints(subimg)
if scaleFactor != 1:
x0 = int(round(x0 * scaleFactor))
y0 = int(round(y0 * scaleFactor))
x = [int(round(subX * scaleFactor)) for subX in x]
y = [int(round(subY * scaleFactor)) for subY in y]
for i in range(len(cnt)):
cnt[i][0][0] = int(round(cnt[i][0][0] * scaleFactor))
cnt[i][0][1] = int(round(cnt[i][0][1] * scaleFactor))
x0 = int(round(x0 / (scaleFactor*self.globalScaleFactor)))
y0 = int(round(y0 / (scaleFactor*self.globalScaleFactor)))
x = [int(round(subX / (scaleFactor*self.globalScaleFactor))) for subX in x]
y = [int(round(subY / (scaleFactor*self.globalScaleFactor))) for subY in y]
for i in range(len(cnt)):
cnt[i][0][0] += left
cnt[i][0][1] += up
cnt[i][0][0] = int(round(cnt[i][0][0] / (scaleFactor*self.globalScaleFactor)) + left)
cnt[i][0][1] = int(round(cnt[i][0][1] / (scaleFactor*self.globalScaleFactor)) + up)
finalcontours.append(cnt)
measurementPoints.append([])
......@@ -372,13 +378,20 @@ class Segmentation(QtCore.QObject):
self.detectionState.emit(f'DO: newVal={label}')
if return_step == 'sure_fg':
if self.globalScaleFactor != 1.:
preview_surefg = cv2.resize(preview_surefg, None, fx=1/self.globalScaleFactor, fy=1/self.globalScaleFactor)
preview_surebg = cv2.resize(preview_surebg, None, fx=1/self.globalScaleFactor, fy=1/self.globalScaleFactor)
img = np.zeros_like(preview_surefg)
img[np.nonzero(preview_surefg)] |= 1
img[np.nonzero(preview_surebg)] |= 2
return img, 1
elif return_step == 'watershed':
return np.uint8(255*(previewImage!=0)), 0
img = np.uint8(255*(previewImage!=0))
if self.globalScaleFactor != 1.:
img = cv2.resize(img, None, fx=1/self.globalScaleFactor, fy=1/self.globalScaleFactor)
return img, 0
elif return_step is not None:
raise NotImplementedError(f"this particular return_step: {return_step} is not implemented yet")
......@@ -386,9 +399,15 @@ class Segmentation(QtCore.QObject):
print("particle detection took:", time()-t0, "seconds")
if self.measurefrac < 1.0:
nMeasurementsDesired = int(np.round(self.measurefrac * len(measurementPoints)))
numMeasPointsOrig = len(measurementPoints)
nMeasurementsDesired = int(np.round(self.measurefrac * numMeasPointsOrig))
print(f'selecting {nMeasurementsDesired} of {len(measurementPoints)} measuring spots')
measurementPoints = random.sample(measurementPoints, nMeasurementsDesired)
measIndices = random.sample(list(np.arange(numMeasPointsOrig)), nMeasurementsDesired)
for partIndex in range(numMeasPointsOrig):
if partIndex not in measIndices:
measurementPoints[partIndex] = []
else:
measIndices.remove(partIndex)
total_time = time()-t0
print('segmentation took', total_time, 'seconds')
......@@ -396,6 +415,12 @@ class Segmentation(QtCore.QObject):
self.detectionState.emit(f'finished particle detection after {total_time} seconds')
return measurementPoints, finalcontours
def getXYRadiusFromSeedPoint(self, seedpoint, scaleFactor=1., left=0, up=0):
x = int(round(seedpoint[0] * scaleFactor) - left)
y = int(round(seedpoint[1] * scaleFactor) - up)
radius = int(round(seedpoint[2] * scaleFactor))
return x, y, radius
def getMinMaxParticleArea(self, dataset):
"""
Converts specified particle sizes into particle areas that are used for filtering detection results.
......@@ -403,7 +428,7 @@ class Segmentation(QtCore.QObject):
a = pi*(d/2)²
:return:
"""
pixelscale = dataset.getPixelScale()
pixelscale = self.getPixelScaleWithComponentScaleFactor(dataset, self.globalScaleFactor)
minRadius = (self.minparticlesize / pixelscale) / 2
minArea = np.pi * minRadius**2
......@@ -415,6 +440,10 @@ class Segmentation(QtCore.QObject):
return minArea, maxArea
def getPixelScaleWithComponentScaleFactor(self, dataset, componentScaleFactor=1.):
pixelscale = dataset.getPixelScale() / (self.globalScaleFactor * componentScaleFactor)
return pixelscale
def addToPreviewImage(self, subimg, up, left, previewImage):
"""
Adds a subimage at given position to the previewimage
......@@ -422,7 +451,7 @@ class Segmentation(QtCore.QObject):
"""
height, width = subimg.shape[0], subimg.shape[1]
previewImage[up:up+height, left:left+width] += subimg
previewImage = np.array(previewImage, dtype = np.int32)
previewImage = np.array(previewImage, dtype = np.uint8)
return previewImage
......@@ -617,8 +646,7 @@ class Segmentation(QtCore.QObject):
if __name__ == '__main__':
import matplotlib.pyplot as plt
# img = cv2.imread('/home/brandt/Schreibtisch/Segmentation/fullimage_III.png')
seg = Segmentation()
kwargs = {}
......@@ -626,22 +654,4 @@ if __name__ == '__main__':
for parameter in seg.parlist:
kwargs[parameter.name] = parameter.value
seg.setParameters(**kwargs)
size = 25000
stepSize = 2000
maxSize = 40000
sizes, times = [], []
while size <= maxSize:
try:
print('newsize =', size)
img = cv2.resize(img, (size, size))
points, contours, tf = seg.apply2Image(img, np.array([]), np.array([]), 1, None)
sizes.append(size)
times.append(tf)
size += stepSize
except:
print('segmentation failed at size', size)
raise
# imgSegmented = cv2.drawContours(img, contours, -1, (255, 255, 0), thickness=2)
# plt.imshow(imgSegmented)
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment