-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAnalysisThread.py
102 lines (84 loc) · 3.47 KB
/
AnalysisThread.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# -*- coding: utf-8 -*-
# @FileName: AnalysisThread.py
# @Time : 2021-03-05 9:55
# @Author : Dorad, [email protected]
# @Blog :https://blog.cuger.cn
from PyQt5.QtCore import QThread, pyqtSignal
from ImageTool import *
# 所有 mask, 0 均是被遮住的部分, 不要的
# basic threshold, global OTSU
class AnalysisThread(QThread):
'''
Analysis Thread for global OTSU
'''
process = pyqtSignal(int)
finish = pyqtSignal(np.ndarray)
def __init__(self):
QThread.__init__(self)
self.grayImage = None
self.labelImage = None
self.edgeMask = None # inner the polygon is True
self.ROIsMaskList = None # inner the ROI is True
def setParameters(self, grayImage: np.array, cropPolygon: QPolygonF = None, ROIs: list = []):
self.grayImage = grayImage
if not cropPolygon:
self.edgeMask = np.zeros((self.grayImage.shape[0], self.grayImage.shape[1]), dtype=bool)
else:
self.edgeMask = QPolygon2Mask(self.grayImage.shape[0], self.grayImage.shape[1], cropPolygon)
self.ROIsMaskList = []
for roi in ROIs:
self.ROIsMaskList.append(
np.logical_and(QPolygon2Mask(self.grayImage.shape[0], self.grayImage.shape[1], roi), self.edgeMask))
def run(self):
if type(self.grayImage) == np.array:
return
self.labelImage = OtsuWithMask2bw(self.grayImage, self.edgeMask == 0)
self.process.emit(100)
self.finish.emit(self.labelImage)
# manual, ROIs to Zones
class ROIsToZonesAnalysisThread(AnalysisThread):
def __init__(self):
AnalysisThread.__init__(self)
def run(self):
bw = np.zeros(self.grayImage.shape, dtype=bool)
for i, roiMask in enumerate(self.ROIsMaskList):
self.process.emit(i / len(self.ROIsMaskList) * 100)
bw = np.logical_or(roiMask, bw)
self.finish.emit(bw)
# SDZM, local binarization for each ROIs
class ROIsOTSUAnalysisThread(AnalysisThread):
def __init__(self):
AnalysisThread.__init__(self)
def run(self):
bw = np.zeros(self.grayImage.shape, dtype=bool)
for i, roiMask in enumerate(self.ROIsMaskList):
self.process.emit(i / len(self.ROIsMaskList) * 100)
roiBw = OtsuWithMask2bw(self.grayImage, roiMask == 0)
bw = np.logical_or(roiBw, bw)
self.finish.emit(bw)
# Riss, the method proposed py Joëlle Riss, https://doi.org/10.1051/mmm:1996153
class RissAnalysisThread(ROIsOTSUAnalysisThread):
def __init__(self):
ROIsOTSUAnalysisThread.__init__(self)
def run(self):
roisMask = np.zeros(self.grayImage.shape, dtype=bool)
for i, roiMask in enumerate(self.ROIsMaskList):
roisMask = np.logical_or(roiMask, roisMask)
self.process.emit(i / len(self.ROIsMaskList) * 100)
# get threshold by riss method based on rois
rissThreshold = self._getRissThresholdWithROIs(self.grayImage, roisMask)
bw = GetBinaryImageWithThresholdWithMask(self.grayImage, self.edgeMask == 0, rissThreshold)
self.finish.emit(bw)
@staticmethod
def _getRissThresholdWithROIs(image: np.array, mask: np.array):
'''
:param image:
:param mask:
:return:
'''
masked = np.ma.masked_array(image, mask == 0)
# calculate the mean and std
mu = np.mean(masked.compressed())
sigma = np.std(masked.compressed())
threshold = mu + 1.96 * sigma
return threshold