OpenCV的滚球背景减除算法

pb3s4cty  于 2023-11-22  发布在  其他
关注(0)|答案(6)|浏览(309)

在ImageJ:Process->Subtract Background中是否有OpenCV(android)实现“rolling ball”背景减除算法?
OpenCV有一个BackgroundSubtractorMOG类,但它用于视频流,而不是单个独立的图像。
下面是该方法的一个示例:https://i.stack.imgur.com/mXSLb.jpg
以下是该过程的文档:http://imagejdocu.tudor.lu/doku.php?id=gui:process:subtract_background

c86crjj0

c86crjj01#

据我所知,OpenCV C库中没有实现,Android JNI Package 器只是围绕主库的 Package 器。
尽管如此,ImageJ实现的源代码可以在here在线获得,因此您应该能够将其直接纳入Android图像处理管道。
有一些关于滚球与使用磁盘结构元素(在OpenCV中可用)here的相对优点的讨论。
如果你绝对需要Rolling Ball和OpenCV,那么不幸的是,它无法“开箱即用”。

mtb9vblg

mtb9vblg2#

在opencv中有一个最近的rolling-ball实现,您可以在这里找到
https://pypi.org/project/opencv-rolling-ball/
总之
安装pip install opencv-rolling-ball
例如

  1. import cv2
  2. from cv2_rolling_ball import subtract_background_rolling_ball
  3. img = cv2.imread(f'path/to/img.tif', 0)
  4. img, background = subtract_background_rolling_ball(img, 30, light_background=True, use_paraboloid=False, do_presmooth=True)

字符串

mrfwxfqh

mrfwxfqh3#

基于@Xenthor的回答,这是我想出来的:

  1. import numpy as np
  2. import scipy.ndimage as ndi
  3. from scipy.ndimage._ni_support import _normalize_sequence
  4. def rolling_ball_filter(data, ball_radius, spacing=None, top=False, **kwargs):
  5. """Rolling ball filter implemented with morphology operations
  6. This implenetation is very similar to that in ImageJ and uses a top hat transform
  7. with a ball shaped structuring element
  8. https://en.wikipedia.org/wiki/Top-hat_transform
  9. Parameters
  10. ----------
  11. data : ndarray
  12. image data (assumed to be on a regular grid)
  13. ball_radius : float
  14. the radius of the ball to roll
  15. spacing : int or sequence
  16. the spacing of the image data
  17. top : bool
  18. whether to roll the ball on the top or bottom of the data
  19. kwargs : key word arguments
  20. these are passed to the ndimage morphological operations
  21. Returns
  22. -------
  23. data_nb : ndarray
  24. data with background subtracted
  25. bg : ndarray
  26. background that was subtracted from the data
  27. """
  28. ndim = data.ndim
  29. if spacing is None:
  30. spacing = 1
  31. spacing = _normalize_sequence(spacing, ndim)
  32. radius = np.asarray(_normalize_sequence(ball_radius, ndim))
  33. mesh = np.array(np.meshgrid(*[np.arange(-r, r + s, s) for r, s in zip(radius, spacing)], indexing="ij"))
  34. structure = 2 * np.sqrt(1 - ((mesh / radius.reshape(-1, *((1,) * ndim)))**2).sum(0))
  35. structure[~np.isfinite(structure)] = 0
  36. if not top:
  37. # ndi.white_tophat(data, structure=structure, output=background)
  38. background = ndi.grey_erosion(data, structure=structure, **kwargs)
  39. background = ndi.grey_dilation(background, structure=structure, **kwargs)
  40. else:
  41. # ndi.black_tophat(data, structure=structure, output=background)
  42. background = ndi.grey_dilation(data, structure=structure, **kwargs)
  43. background = ndi.grey_erosion(background, structure=structure, **kwargs)
  44. return data - background, background

字符串

展开查看全部
ih99xse1

ih99xse14#

**编辑:**在使用本文中的方法之前,请阅读下面的评论,并考虑@renat和@大卫霍夫曼的答案。

如果有人还在寻找python中的滚动球背景校正。对我来说,下面的工作非常好。
1.加载图像并单独处理每个通道。
1.创建加权球结构元素
1.使用白色礼帽变换
下面是一些单色图像的代码:

  1. import scipy.ndimage as scim
  2. from scipy.misc import imsave
  3. from skimage.morphology import ball
  4. # Read image
  5. im = scim.imread("path")[:, :, 0].astype(int)
  6. # Create 3D ball with radius of 50 and a diameter of 2*50+1
  7. s = ball(50)
  8. # Take only the upper half of the ball
  9. h = s.shape[1] // 2 + 1 # 50 + 1
  10. # Flatten the 3D ball to a weighted 2D disc
  11. s = s[:h, :, :].sum(axis=0)
  12. # Rescale weights into 0-255
  13. s = (255 * (s - s.min())) / (s.max() - s.min())
  14. # Use im-opening(im,ball) (i.e. white tophat transform) (see original publication)
  15. im_corr = scim.white_tophat(im, structure=s)
  16. # Save corrected image
  17. imsave('outfile', im_corr)

字符串
这给你的结果与imagej实现不完全相同,但结果非常相似。在我的例子中,有更好和更差的校正区域。此外,整体颜色强度更高。

展开查看全部
but5z9lq

but5z9lq5#

ImageJ实现的原始算法来自1983年的一篇论文https://www.computer.org/csdl/magazine/co/1983/01/01654163/13rRUwwJWBB。我看了一下,它实际上是一个带有球形灰度结构元素的灰度形态学白色礼帽(参见https://en.wikipedia.org/wiki/Top-hat_transform)。在ImageJ实现中,(此处可用https://imagej.nih.gov/ij/developer/source/ij/plugin/filter/BackgroundSubtracter.java.html),根据结构元素的半径对图像进行下采样,然后上采样到原始分辨率,默认情况下,在计算要减去的背景之前,应用使用3 × 3均值滤波器的平滑操作。2这可能解释了用Xenthor提出的方法观察到的差异。
如果你在Android上工作,你有几个选择:1)使用ImageJ库,因为它是在Java中,你将需要实现一个OpenCV-ImageJ图像桥; 2)如果你在C中使用Android NDK工作,因为OpenCV不为非平面结构元素实现灰度形态,你可以使用ITK(https://itk.org/)来执行灰度白色礼帽; 3)仍然使用NDK,这里有一个基于OpenCV的算法的C端口:https://github.com/folterj/BioImageOperation/tree/master/BioImageOperation,但它仍然是一个正在进行的工作。

dl5txlt9

dl5txlt96#

我知道它不是opencv,但在scikit-image(版本≥ 0.18)中有一个实现。

  1. from skimage import data, restoration
  2. image = data.coins()
  3. background = restoration.rolling_ball(image, radius=100)
  4. result = image - background

字符串
documentation中提供了更详细的演练

相关问题