Skip to content

Commit 72808a3

Browse files
author
yxdragon
committed
compleximage view support
1 parent f22ef8a commit 72808a3

File tree

7 files changed

+148
-71
lines changed

7 files changed

+148
-71
lines changed

imagepy/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import wx.lib.agw.advancedsplash as AS
77

88
from .IPy import *
9+
from .core import ImagePlus, TablePlus
910
root_dir = osp.abspath(osp.dirname(__file__))
1011
os.chdir(root_dir)
1112

imagepy/core/manager/windowmanager.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ def remove(cls, win):
2626
for i in cls.wins:
2727
if i == win:
2828
cls.wins.remove(i)
29-
print('remove', i.ips.title)
3029

3130
class ImageManager:
3231
imgs = []

imagepy/core/wraper/imageplus.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ def get_img_type(imgs):
99
if imgs[0].dtype == np.int32:return '32-int'
1010
if imgs[0].dtype == np.float32:return '32-float'
1111
if imgs[0].dtype == np.float64:return '64-float'
12-
if imgs[0].dtype == np.complex128:return 'complex'
12+
if imgs[0].dtype == np.complex128:return '128-complex'
13+
if imgs[0].dtype == np.complex64:return '64-complex'
1314

1415
def get_updown(imgs, slices='all', chans='all', step=1):
1516
c = chans if isinstance(chans, int) else slice(None)
@@ -23,6 +24,8 @@ def get_updown(imgs, slices='all', chans='all', step=1):
2324
mins = np.array(mins).reshape((len(mins),-1))
2425
maxs = np.array(maxs).reshape((len(maxs),-1))
2526
mins, maxs = mins.min(axis=0), maxs.max(axis=0)
27+
if np.iscomplexobj(mins):
28+
mins, maxs = np.zeros(mins.shape), np.abs(maxs)
2629
if chans!='all': return mins.min(), maxs.max()
2730
return [(i,j) for i,j in zip(mins, maxs)]
2831

@@ -50,6 +53,7 @@ def __init__(self, imgs, title=None, is3d=False):
5053
self.msk = None
5154
self.mskmode = None
5255
self.lut = ColorManager.get_lut('grays')
56+
self.log = False
5357

5458
self.tool = None
5559
self.data = {}

imagepy/menus/Process/FFT/fft_plgs.py

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from imagepy.core.engine import Simple, Filter
33
from numpy.fft import fft2, ifft2, fftshift, ifftshift
44
from imagepy import IPy
5+
from imagepy.core import ImagePlus
56

67
class FFT(Simple):
78
title = 'FFT'
@@ -17,26 +18,9 @@ def run(self, ips, imgs, para = None):
1718
for i in range(len(imgs)):
1819
rst.append(shift(fft2(imgs[i])))
1920
self.progress(i, len(imgs))
20-
IPy.show_img(rst, '%s-fft'%ips.title)
21-
22-
class LogPower(Simple):
23-
title = 'Log Power'
24-
note = ['complex']
25-
para = {'slice':False, 'type':'float', 'log':2.718}
26-
view = [(float, 'log', (2,30), 3, 'log', ''),
27-
(list, 'type', ['uint8', 'int', 'float'], str, 'type', ''),
28-
(bool, 'slice', 'slices')]
29-
30-
def run(self, ips, imgs, para = None):
31-
if not para['slice']: imgs = [ips.img]
32-
tp = {'uint8':np.uint8, 'int':np.int32, 'float':np.float32}
33-
rst, tp = [], tp[para['type']]
34-
for i in range(len(imgs)):
35-
zs = np.log(np.abs(imgs[i]))
36-
zs /= np.log(para['log'])
37-
rst.append(zs.astype(tp))
38-
self.progress(i, len(imgs))
39-
IPy.show_img(rst, '%s-fft'%ips.title)
21+
ips = ImagePlus(rst, '%s-fft'%ips.title)
22+
ips.log = True
23+
IPy.show_ips(ips)
4024

4125
class IFFT(Simple):
4226
title = 'Inverse FFT'
@@ -70,4 +54,22 @@ class IShift(Filter):
7054
def run(self, ips, snap, img, para = None):
7155
return ifftshift(img)
7256

73-
plgs = [FFT, IFFT, '-', Shift, IShift, LogPower]
57+
class Split(Simple):
58+
title = 'Split Real And Image'
59+
note = ['complex']
60+
para = {'slice':False, 'copy':False}
61+
view = [(bool, 'slice', 'slices'),
62+
(bool, 'copy', 'memory copy')]
63+
64+
def run(self, ips, imgs, para = None):
65+
if not para['slice']: imgs = [ips.img]
66+
copy = np.copy if para['copy'] else lambda x:x
67+
imags, reals = [], []
68+
for i in range(len(imgs)):
69+
reals.append(copy(imgs[i].real))
70+
imags.append(copy(imgs[i].imag))
71+
self.progress(i, len(imgs))
72+
IPy.show_img(reals, '%s-real'%ips.title)
73+
IPy.show_img(imags, '%s-image'%ips.title)
74+
75+
plgs = [FFT, IFFT, '-', Shift, IShift, '-', Split]

imagepy/ui/canvas/canvas.py

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,19 @@ def __init__(self, parent, autofit=False):
2525

2626
self.buffer = None
2727

28-
lut = np.arange(256*3)
28+
lut = np.arange(256*3)//3
2929
lut.shape = (256,3)
3030
lut = lut.astype(np.uint8)
3131

3232
self.lut = lut
3333
self.rg = (0, 255)
3434
self.cn = 0
35+
self.log = False
3536

3637
self._lut = lut
3738
self._rg = (0, 255)
3839
self._cn = 0
40+
self._log = False
3941

4042
self.marks = {}
4143

@@ -99,6 +101,10 @@ def set_img(self, img):
99101
def set_back(self, back):
100102
self.back = back
101103

104+
def set_log(self, log, b=False):
105+
if b: self._log = log
106+
else: self.log = log
107+
102108
def set_rg(self, rg, b=False):
103109
if b: self._rg = rg
104110
else: self.rg = rg
@@ -158,17 +164,17 @@ def draw_image(self, dc, img, back, mode):
158164

159165
#if not back is None: print('has back image')
160166
mix_img(back, m, o, shp, self.outbak,
161-
self.outrgb, self.outint,
162-
self._rg, self._lut, cns=self._cn, mode='set')
167+
self.outrgb, self.outint, self._rg,
168+
self._lut, self._log, cns=self._cn, mode='set')
163169

164170
mix_img(self.img, m, o, shp, self.outimg,
165-
self.outrgb, self.outint,
166-
self.rg, self.lut, cns=self.cn, mode=self.mode)
167-
171+
self.outrgb, self.outint, self.rg,
172+
self.lut, self.log, cns=self.cn, mode=self.mode)
168173
self.outbmp.CopyFromBuffer(memoryview(self.outrgb))
169174
dc.DrawBitmap(self.outbmp, *csbox[:2])
170175

171-
def update(self):
176+
def update(self, counter = [0,0]):
177+
counter[0] += 1
172178
start = time()
173179
lay(self.winbox, self.conbox)
174180
dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
@@ -181,8 +187,11 @@ def update(self):
181187
else:
182188
drawmark(dc, self.to_panel_coor, self.marks[i], k=self.scale)
183189
dc.UnMask()
184-
print('frame rate:',int(1/max(0.001, time()-start)))
185-
190+
counter[1] += time()-start
191+
if counter[0] == 10:
192+
print('frame rate:',int(10/max(0.001,counter[1])))
193+
counter[0] = counter[1] = 0
194+
186195
def center(self, x, y, coord='win'):
187196
if coord=='data':
188197
x,y = self.to_panel_coor(x, y)
@@ -229,24 +238,27 @@ def __del__(self):
229238
print('========== canvas del')
230239

231240
if __name__=='__main__':
232-
msk = np.zeros((512,512), dtype=np.uint8)
233-
msk[100:200,100:200] = 1
234-
msk[200:300,200:300] = 2
235-
msk[300:400,300:400] = 3
236-
lut = np.array([(0,0,0),(255,0,0),(0,255,0),(0,0,255)], dtype=np.uint8)
237-
238241
from skimage.data import astronaut, camera
242+
from numpy.fft import fft2, ifft2, fftshift, ifftshift
243+
import matplotlib.pyplot as plt
244+
245+
img = camera()
246+
img = fftshift(fft2(img))
247+
farr = img.view(dtype=np.float64)
248+
#a = farr.reshape((512,2,512)).transpose(0,2,1)
249+
# farr.shape = img.shape+(-1,)
250+
#plt.imshow(np.log(np.abs(a[:,:,1])))
251+
#plt.show()
252+
239253
app = wx.App()
240254
frame = wx.Frame(None)
241255
canvas = Canvas(frame)
242-
canvas.set_img(msk)
243-
canvas.set_lut(lut)
256+
257+
canvas.set_img(img)
258+
# canvas.set_rg((-128, 127))
259+
canvas.set_rg((0,31015306))
244260
canvas.set_cn(0)
245-
canvas.set_back(astronaut())
246-
canvas.set_cn((0,1,2), True)
247-
canvas.set_mode(0.5)
248-
x = np.arange(512)
249-
y = np.sin(x/30) * 100 + 256
250-
canvas.marks['line'] = {'type':'line', 'lw':3, 'body':np.array([x,y]).T.tolist()}
261+
canvas.set_log(True)
251262
frame.Show(True)
263+
frame.SetSize(512,512)
252264
app.MainLoop()

imagepy/ui/canvas/imutil.py

Lines changed: 82 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import numpy as np
22
from scipy.ndimage import affine_transform
33
try: from numba import njit as jit
4-
except: jit = None
4+
except:
5+
print('install numba may be several times faster!')
6+
jit = None
57
# jit = None
6-
8+
79
def affine_jit(img, m, offset, output_shape=0, output=0, order=0, prefilter=0):
810
kr=m[0]; kc=m[1]; ofr=offset[0]; ofc=offset[1];
911
for r in range(output_shape[0]):
@@ -61,34 +63,88 @@ def blend_jit(img, out, msk, mode):
6163
if isinstance(mode, float): blend_mix(img, out, msk, mode)
6264
blend = blend_jit
6365

64-
def stretch(img, out, rg, mode='set'):
65-
if img.dtype==np.uint8 and (rg==[(0,255)] or rg==(0,255)):
66+
def stretch(img, out, rg, log=False):
67+
if img.dtype==np.uint8 and not log and (rg==[(0,255)] or rg==(0,255)):
6668
out[:] = img
67-
else:
69+
elif not log:
70+
ptp = max(rg[1]-rg[0], 1e-6)
6871
np.clip(img, rg[0], rg[1], out=img)
6972
np.subtract(img, rg[0], out=img, casting='unsafe')
70-
np.multiply(img, 255.0/np.ptp(rg), out=out, casting='unsafe')
73+
np.multiply(img, 255/ptp, out=out, casting='unsafe')
74+
elif img.itemsize<3:
75+
length = 2**(img.itemsize*8)
76+
lut = np.arange(length, dtype=np.float32)
77+
if img.dtype in (np.int8, np.int16):
78+
lut[length//2:] -= length
79+
np.clip(lut, rg[0], rg[1], out=lut)
80+
np.subtract(lut, rg[0]-1, out=lut)
81+
ptp = np.log(max(rg[1]-rg[0]+1, 1+1e-6))
82+
np.log(lut, out=lut)
83+
lut *= 255/np.log(max(rg[1]-rg[0]+1, 1+1e-6))
84+
out[:] = lut[img]
85+
else:
86+
fimg = img.ravel().view(np.float32)
87+
fimg = fimg[:img.size].reshape(img.shape)
88+
np.clip(img, rg[0], rg[1], out=fimg)
89+
np.subtract(fimg, rg[0]-1, out=fimg)
90+
ptp = np.log(max(rg[1]-rg[0]+1, 1+1e-6))
91+
np.log(fimg, out=fimg)
92+
np.multiply(fimg, 255/ptp, out=out, casting='unsafe')
7193

7294
if not jit is None:
7395
@jit
74-
def stretch_int(img, out, rg):
96+
def stretch_linear(img, out, rg):
97+
ptp = max(rg[1]-rg[0], 1e-6)
7598
for r in range(img.shape[0]):
7699
for c in range(img.shape[1]):
77-
out[r,c] = img[r,c]
100+
v = (img[r,c]-rg[0])/ptp*255
101+
out[r,c] = min(max(v, 0), 255)
78102
@jit
79-
def stretch_other(img, out, rg):
80-
ptp = max(rg[1]-rg[0], 1e-6)
103+
def stretch_log(img, out, rg):
104+
ptp = 255/np.log(max(rg[1]-rg[0]+1, 1+1e-6))
81105
for r in range(img.shape[0]):
82106
for c in range(img.shape[1]):
83-
v = (img[r,c]-rg[0])/ptp*255
107+
v = np.log(img[r,c]-rg[0]+1)*ptp
84108
out[r,c] = min(max(v, 0), 255)
85-
def stretch_jit(img, out, rg):
86-
# print(img.dtype, rg)
87-
if img.dtype==np.uint8 and (rg==[(0,255)] or rg==(0,255)):
88-
stretch_int(img, out, rg)
89-
else: stretch_other(img, out, rg)
109+
@jit
110+
def stretch_lut(img, out, lut):
111+
for r in range(img.shape[0]):
112+
for c in range(img.shape[1]):
113+
out[r,c] = lut[img[r,c]]
114+
115+
def stretch_jit(img, out, rg, log=False):
116+
if img.dtype==np.uint8 and not log and (rg==[(0,255)] or rg==(0,255)):
117+
out[:] = img
118+
elif not log:
119+
stretch_linear(img, out, rg)
120+
elif img.itemsize<3:
121+
length = 2**(img.itemsize*8)
122+
lut = np.arange(length, dtype=np.float32)
123+
if img.dtype in (np.int8, np.int16):
124+
lut[length//2:] -= length
125+
np.clip(lut, rg[0], rg[1], out=lut)
126+
np.subtract(lut, rg[0]-1, out=lut)
127+
ptp = np.log(max(rg[1]-rg[0]+1, 1+1e-6))
128+
np.log(lut, out=lut)
129+
lut *= 255/np.log(max(rg[1]-rg[0]+1, 1+1e-6))
130+
stretch_lut(img, out, lut)
131+
else:
132+
stretch_log(img, out, rg)
133+
90134
stretch = stretch_jit
91135

136+
def complex_norm(ori, real, img, out):
137+
np.abs(ori, out=out)
138+
return out
139+
140+
if not jit is None:
141+
@jit
142+
def complex_norm(ori, real, img, out):
143+
for r in range(img.shape[0]):
144+
for c in range(img.shape[1]):
145+
out[r,c] = (img[r,c]**2+real[r,c]**2)**0.5
146+
return out
147+
92148
def lookup(img, lut, out, mode='set'):
93149
blend(lut[img], out, img, mode)
94150

@@ -136,29 +192,30 @@ def lookup_jit(img, lut, out, mode):
136192
lookup = lookup_jit
137193

138194
# mode: set, min, max, mix, nor
139-
def mix_img(img, m, o, shp, buf, rgb, byt, rg=(0,255), lut=None, cns=0, mode='set'):
195+
def mix_img(img, m, o, shp, buf, rgb, byt, rg=(0,255), lut=None, log=True, cns=0, mode='set'):
140196
if img is None: return
141197
img = img.reshape((img.shape[0], img.shape[1], -1))
142198
if isinstance(rg, tuple): rg = [rg]*img.shape[2]
143199

144200
if isinstance(cns, int):
145-
# print(img.dtype, buf.dtype, 'type')
146-
affine_transform(img[:,:,cns], m, o, shp, buf, 0, prefilter=False)
147-
stretch(buf, byt, rg[cns])
201+
if np.iscomplexobj(buf):
202+
affine_transform(img[:,:,0].real, m, o, shp, buf.real, 0, prefilter=False)
203+
affine_transform(img[:,:,0].imag, m, o, shp, buf.imag, 0, prefilter=False)
204+
buf = complex_norm(buf, buf.real, buf.imag, buf.real)
205+
else: affine_transform(img[:,:,cns], m, o, shp, buf, 0, prefilter=False)
206+
stretch(buf, byt, rg[cns], log)
148207
return lookup(byt, lut, rgb, mode)
149-
150208
for i,v in enumerate(cns):
151209
if v==-1: rgb[:,:,i] = 0
152-
elif mode=='set' and buf.dtype==np.uint8 and rg[v]==(0,255):
210+
elif mode=='set' and img.dtype==np.uint8 and rg[v]==(0,255) and not log:
153211
affine_transform(img[:,:,v], m, o, shp, rgb[:,:,i], 0, prefilter=False)
154212
else:
155213
affine_transform(img[:,:,v], m, o, shp, buf, 0, prefilter=False)
156-
stretch(buf, byt, rg[v])
214+
stretch(buf, byt, rg[v], log)
157215
blend(byt, rgb[:,:,i], byt, mode)
158216

159-
160217
'''
161218
rgb = np.array([[[0,0,0]]], dtype=np.uint8)
162219
lut = np.array([[0,0,0]], dtype=np.uint8)
163220
mix_img(img, (1,1), (0,0), (1,1), img, rgb, img, (0,255), lut, 0, 'set')
164-
'''
221+
'''

imagepy/ui/canvasframe.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,13 @@ def on_idle(self, event):
130130
self.canvas.set_img(self.ips.imgs[self.ips.cur])
131131
self.canvas.set_cn(self.ips.chan)
132132
self.canvas.set_rg(self.ips.chan_range)
133+
self.canvas.set_log(self.ips.log)
133134

134135
if self.ips.back != None:
135136
self.ips.back.cur = self.ips.cur
136137
self.canvas.set_back(self.ips.back.img)
137138
self.canvas.set_cn(self.ips.back.chan, True)
139+
self.canvas.set_log(self.ips.back.log, True)
138140
self.canvas.set_rg(self.ips.back.chan_range, True)
139141
self.canvas.set_lut(self.ips.back.lut, True)
140142
self.canvas.set_mode(self.ips.chan_mode)

0 commit comments

Comments
 (0)