iproc.lua 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. local gm = {}
  2. gm.Image = require 'graphicsmagick.Image'
  3. local image = nil
  4. require 'dok'
  5. require 'image'
  6. local iproc = {}
  7. local clip_eps8 = (1.0 / 255.0) * 0.5 - (1.0e-7 * (1.0 / 255.0) * 0.5)
  8. function iproc.crop_mod4(src)
  9. local w = src:size(3) % 4
  10. local h = src:size(2) % 4
  11. return iproc.crop(src, 0, 0, src:size(3) - w, src:size(2) - h)
  12. end
  13. function iproc.crop(src, w1, h1, w2, h2)
  14. local dest
  15. if src:dim() == 3 then
  16. dest = src[{{}, { h1 + 1, h2 }, { w1 + 1, w2 }}]:clone()
  17. else -- dim == 2
  18. dest = src[{{ h1 + 1, h2 }, { w1 + 1, w2 }}]:clone()
  19. end
  20. return dest
  21. end
  22. function iproc.crop_nocopy(src, w1, h1, w2, h2)
  23. local dest
  24. if src:dim() == 3 then
  25. dest = src[{{}, { h1 + 1, h2 }, { w1 + 1, w2 }}]
  26. else -- dim == 2
  27. dest = src[{{ h1 + 1, h2 }, { w1 + 1, w2 }}]
  28. end
  29. return dest
  30. end
  31. function iproc.byte2float(src)
  32. local conversion = false
  33. local dest = src
  34. if src:type() == "torch.ByteTensor" then
  35. conversion = true
  36. dest = src:float():div(255.0)
  37. end
  38. return dest, conversion
  39. end
  40. function iproc.float2byte(src)
  41. local conversion = false
  42. local dest = src
  43. if src:type() == "torch.FloatTensor" then
  44. conversion = true
  45. dest = (src + clip_eps8):mul(255.0)
  46. dest:clamp(0, 255.0)
  47. dest = dest:byte()
  48. end
  49. return dest, conversion
  50. end
  51. function iproc.scale(src, width, height, filter, blur)
  52. local conversion, color
  53. src, conversion = iproc.byte2float(src)
  54. filter = filter or "Box"
  55. if src:size(1) == 3 then
  56. color = "RGB"
  57. else
  58. color = "I"
  59. end
  60. local im = gm.Image(src, color, "DHW")
  61. im:size(math.ceil(width), math.ceil(height), filter, blur)
  62. local dest = im:toTensor("float", color, "DHW")
  63. if conversion then
  64. dest = iproc.float2byte(dest)
  65. end
  66. return dest
  67. end
  68. function iproc.scale_with_gamma22(src, width, height, filter, blur)
  69. local conversion
  70. src, conversion = iproc.byte2float(src)
  71. filter = filter or "Box"
  72. local im = gm.Image(src, "RGB", "DHW")
  73. im:gammaCorrection(1.0 / 2.2):
  74. size(math.ceil(width), math.ceil(height), filter, blur):
  75. gammaCorrection(2.2)
  76. local dest = im:toTensor("float", "RGB", "DHW"):clamp(0.0, 1.0)
  77. if conversion then
  78. dest = iproc.float2byte(dest)
  79. end
  80. return dest
  81. end
  82. function iproc.padding(img, w1, w2, h1, h2)
  83. image = image or require 'image'
  84. local dst_height = img:size(2) + h1 + h2
  85. local dst_width = img:size(3) + w1 + w2
  86. local flow = torch.Tensor(2, dst_height, dst_width)
  87. flow[1] = torch.ger(torch.linspace(0, dst_height -1, dst_height), torch.ones(dst_width))
  88. flow[2] = torch.ger(torch.ones(dst_height), torch.linspace(0, dst_width - 1, dst_width))
  89. flow[1]:add(-h1)
  90. flow[2]:add(-w1)
  91. return image.warp(img, flow, "simple", false, "clamp")
  92. end
  93. function iproc.zero_padding(img, w1, w2, h1, h2)
  94. image = image or require 'image'
  95. local dst_height = img:size(2) + h1 + h2
  96. local dst_width = img:size(3) + w1 + w2
  97. local flow = torch.Tensor(2, dst_height, dst_width)
  98. flow[1] = torch.ger(torch.linspace(0, dst_height -1, dst_height), torch.ones(dst_width))
  99. flow[2] = torch.ger(torch.ones(dst_height), torch.linspace(0, dst_width - 1, dst_width))
  100. flow[1]:add(-h1)
  101. flow[2]:add(-w1)
  102. return image.warp(img, flow, "simple", false, "pad", 0)
  103. end
  104. function iproc.white_noise(src, std, rgb_weights, gamma)
  105. gamma = gamma or 0.454545
  106. local conversion
  107. src, conversion = iproc.byte2float(src)
  108. std = std or 0.01
  109. local noise = torch.Tensor():resizeAs(src):normal(0, std)
  110. if rgb_weights then
  111. noise[1]:mul(rgb_weights[1])
  112. noise[2]:mul(rgb_weights[2])
  113. noise[3]:mul(rgb_weights[3])
  114. end
  115. local dest
  116. if gamma ~= 0 then
  117. dest = src:clone():pow(gamma):add(noise)
  118. dest:clamp(0.0, 1.0)
  119. dest:pow(1.0 / gamma)
  120. else
  121. dest = src + noise
  122. end
  123. if conversion then
  124. dest = iproc.float2byte(dest)
  125. end
  126. return dest
  127. end
  128. function iproc.hflip(src)
  129. local t
  130. if src:type() == "torch.ByteTensor" then
  131. t = "byte"
  132. else
  133. t = "float"
  134. end
  135. if src:size(1) == 3 then
  136. color = "RGB"
  137. else
  138. color = "I"
  139. end
  140. local im = gm.Image(src, color, "DHW")
  141. return im:flop():toTensor(t, color, "DHW")
  142. end
  143. function iproc.vflip(src)
  144. local t
  145. if src:type() == "torch.ByteTensor" then
  146. t = "byte"
  147. else
  148. t = "float"
  149. end
  150. if src:size(1) == 3 then
  151. color = "RGB"
  152. else
  153. color = "I"
  154. end
  155. local im = gm.Image(src, color, "DHW")
  156. return im:flip():toTensor(t, color, "DHW")
  157. end
  158. function iproc.gaussian2d(kernel_size, sigma)
  159. sigma = sigma or 1
  160. local kernel = torch.Tensor(kernel_size, kernel_size)
  161. local u = math.floor(kernel_size / 2) + 1
  162. local amp = (1 / math.sqrt(2 * math.pi * sigma^2))
  163. for x = 1, kernel_size do
  164. for y = 1, kernel_size do
  165. kernel[x][y] = amp * math.exp(-((x - u)^2 + (y - u)^2) / (2 * sigma^2))
  166. end
  167. end
  168. kernel:div(kernel:sum())
  169. return kernel
  170. end
  171. local function test_conversion()
  172. local a = torch.linspace(0, 255, 256):float():div(255.0)
  173. local b = iproc.float2byte(a)
  174. local c = iproc.byte2float(a)
  175. local d = torch.linspace(0, 255, 256)
  176. assert((a - c):abs():sum() == 0)
  177. assert((d:float() - b:float()):abs():sum() == 0)
  178. a = torch.FloatTensor({256.0, 255.0, 254.999}):div(255.0)
  179. b = iproc.float2byte(a)
  180. assert(b:float():sum() == 255.0 * 3)
  181. a = torch.FloatTensor({254.0, 254.499, 253.50001}):div(255.0)
  182. b = iproc.float2byte(a)
  183. print(b)
  184. assert(b:float():sum() == 254.0 * 3)
  185. end
  186. local function test_flip()
  187. require 'sys'
  188. require 'torch'
  189. torch.setdefaulttensortype("torch.FloatTensor")
  190. image = require 'image'
  191. local src = image.lena()
  192. local src_byte = src:clone():mul(255):byte()
  193. print(src:size())
  194. print((image.hflip(src) - iproc.hflip(src)):sum())
  195. print((image.hflip(src_byte) - iproc.hflip(src_byte)):sum())
  196. print((image.vflip(src) - iproc.vflip(src)):sum())
  197. print((image.vflip(src_byte) - iproc.vflip(src_byte)):sum())
  198. end
  199. local function test_gaussian2d()
  200. local t = {3, 5, 7}
  201. for i = 1, #t do
  202. local kp = iproc.gaussian2d(t[i], 0.5)
  203. print(kp)
  204. end
  205. end
  206. local function test_conv()
  207. local image = require 'image'
  208. local src = image.lena()
  209. local kernel = torch.Tensor(3, 3):fill(1)
  210. kernel:div(kernel:sum())
  211. --local blur = image.convolve(iproc.padding(src, 1, 1, 1, 1), kernel, 'valid')
  212. local blur = image.convolve(src, kernel, 'same')
  213. print(src:size(), blur:size())
  214. local diff = (blur - src):abs()
  215. image.save("diff.png", diff)
  216. image.display({image = blur, min=0, max=1})
  217. image.display({image = diff, min=0, max=1})
  218. end
  219. --test_conversion()
  220. --test_flip()
  221. --test_gaussian2d()
  222. --test_conv()
  223. return iproc