- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
下面的代码通过将小像素合并为较大像素来降低 2D numpy 数组(图像)的分辨率。我想知道它是否可以做得更快,或者是否有更快的替代方案。此外,任何一般建议都会受到赞赏。例如,如果有一个代码速度相似,但生成更平滑的缩小图像(例如通过使用样条线)
import numpy as np
def reduce_img ( img, bin_fac=1 ):
assert( len( img.shape ) == 2 )
imgX0 = img.shape[0] # slow axis
imgX1 = img.shape[1] # fast axis
r0 = imgX0 % bin_fac
r1 = imgX1 % bin_fac
img = np.copy( img) [:imgX0 - r0, :imgX1-r1]
# bin the fast axis
img_C = img.ravel(order='C')
img = np.average( [ img_C[i::bin_fac] for i in xrange( bin_fac ) ],axis=0)
img = img.reshape( (imgX0-r0, (imgX1-r1)/bin_fac ) , order='C')
# bin the slow axis
img_F = img.ravel(order='F')
img = np.average( [ img_F[i::bin_fac] for i in xrange( bin_fac ) ],axis=0)
img = img.reshape( ((imgX0-r0)/bin_fac, (imgX1-r1)/bin_fac ), order='F' )
return img
这是一个结果
>> from pylab import *
>> imshow( img )
>> show()
>> img_r = reduce_img( img, bin_fac = 7 )
>> imshow( img_r )
>> show()
>> %timeit( reduce_img( img, bin_fac=7) )
1000 loops, best of 3: 655 µs per loop
最佳答案
我首先要提到的是,您的分箱方式似乎相当不寻常,我想这就是@ljetibo 在评论中所指的内容。在“优化”演讲之后我会再回到这个话题。
首先,您可以通过删除对 np.copy
的多余调用来稍微改进您的代码,因为您只是重新绑定(bind) img
到传入的 img
View 。 ravel 操作将返回一个副本,除非图像形状是分箱因子 bin_fac 的倍数。
现在,虽然列表推导速度很快,但您正在从可能不连续的列表重新创建 numpy 数组,这意味着您再次将内存从一个位置复制到另一个位置。这些都是会降低效率的操作。
您可能感兴趣的只是在原始图像上生成高内存效率的 View 。这就是 as_strided
发挥作用的地方:
from numpy.lib.stride_tricks import as_strided
def strided_rescale(g, bin_fac):
strided = as_strided(g,
shape=(g.shape[0]//bin_fac, g.shape[1]//bin_fac, bin_fac, bin_fac),
strides=((g.strides[0]*bin_fac, g.strides[1]*bin_fac)+g.strides))
return strided.mean(axis=-1).mean(axis=-1) # order is NOT important! See notes..
时序考虑表明,这通常比原始方法要快一些,随着分箱因子的增加,性能会有所提高:
In [263]: stp = 'from __main__ import img, strided_rescale, reduce_img'
In [264]: for n in range(1,21):
a = timeit.timeit(stmt='strided_rescale(img, {})'.format(n), setup=stp, number=100)
b = timeit.timeit(stmt='reduce_img(img, {})'.format(n), setup=stp, number=100)
c = b*1./a
d = np.ptp(strided_rescale(img, n) - reduce_img(img,n))
print('{a:7f} | {b:7f} | {c:1.4f} | {d:1.4g}'.format(**locals()))
.....:
0.124911 | 0.277254 | 2.2196 | 0
0.303813 | 0.171833 | 0.5656 | 0
0.217745 | 0.188637 | 0.8663 | 0
0.162199 | 0.139770 | 0.8617 | 0
0.132355 | 0.138402 | 1.0457 | 0
0.121542 | 0.160275 | 1.3187 | 0
0.102930 | 0.162041 | 1.5743 | 0
0.090694 | 0.138881 | 1.5313 | 2.384e-07
0.097320 | 0.174690 | 1.7950 | 1.788e-07
0.082376 | 0.155261 | 1.8848 | 2.384e-07
0.084228 | 0.178397 | 2.1180 | 2.98e-07
0.070411 | 0.181175 | 2.5731 | 2.98e-07
0.075443 | 0.175605 | 2.3277 | 5.96e-08
0.068964 | 0.182602 | 2.6478 | 5.96e-08
0.067155 | 0.168532 | 2.5096 | 1.192e-07
0.056193 | 0.195684 | 3.4824 | 2.98e-07
0.063575 | 0.206987 | 3.2558 | 2.98e-07
0.078850 | 0.187697 | 2.3804 | 2.384e-07
0.053072 | 0.168763 | 3.1799 | 2.384e-07
0.047512 | 0.151598 | 3.1907 | 1.788e-07
# time a | time b | b/a | peak-to-peak: check if both arrays are the same
我相信观察到的数组相等性的微小差异是由于复制操作造成的,在复制操作中,您从 numpy 数据类型返回到普通的 Python float ,反之亦然。不过我对此并不是 100% 确定。
现在优化讨论已经结束,让我们回到您的分箱方法。在当前的实现中,您已将图像分割为方形、不重叠的区域。对于这个故事的其余部分,这些子矩阵不必是正方形的,它们可以是矩形的(如果可以改变图像的纵横比),并且结论仍然有效。因此,在每个子矩阵中,您将取行方向平均值,然后取所得列向量的平均值。可以很容易地从数学角度证明这与对整个子矩阵求平均值相同。这是个好消息,因为这意味着在上面显示的 strided_rescale
函数中,您可以简单地将 return
语句替换为:
return gstr.mean(axis=(-2,-1))
这将给你带来另一个(小)速度提升。
我认为建议使用 scipy.misc.imresize
是一个非常好的方法,直到我在 dtype != np.uint8 的 ndarrays 上尝试它。即使如此,也必须正确选择 mode
参数,并且它似乎只采用子矩阵的左上角:
In [39]: a = np.arange(16, dtype=np.uint8).reshape(4,4)
In [40]: a
Out[40]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]], dtype=uint8)
In [41]: imresize(a, (2,2), mode='P')
Out[41]:
array([[ 0, 2],
[ 8, 10]], dtype=uint8)
In [42]: imresize(a, (2,2), mode='L')
Out[42]:
array([[0, 1],
[6, 7]], dtype=uint8)
这可能不是您想要的。所以 stride_tricks 对于实际的分箱效果很好。如果您想要平滑调整大小行为(例如通过使用样条插值),您将关注Python图像库以及所有在幕后使用它的函数,例如OpenCV,它还提供调整大小行为 summarized in this post .
关于使用 numpy 快速降低图像分辨率的 Python 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28906298/
如何更改循环中变量的名称?比如 number1 、 number2 、 number3 、 number4 ? var array = [2,4,6,8] func ap ( number1: Int
我想设置 View 的背景颜色并在一定延迟后将其更改为另一种颜色。这是我的尝试方式: print("setting color 1") self.view.backgroundColor = UICo
我在使用 express-session 时遇到问题。 session 数据不会在请求之间持续存在。 正如您在下面的代码中看到的那样,/join 路由设置了一些 session 属性,但是当 /sur
我试图从叶渲染器获得一个非常简单的结果,用于快速 Steam 的 for 循环。 我正在上传叶文件 HTML,因为它不接受此处格式正确的代码 - 下面的pizza.swift代码- import
你们中有人有什么好的链接可以与我分享吗?我正在寻找一个 FAST 程序员编辑器,它可以非常快速地打开包含超过 100, 000 行代码的文件?我目前正在使用记事本自动取款机,打开一个 29000 行长
我现在正在处理眼动追踪数据,因此拥有一个巨大的数据集(想想数百万行),因此希望有一种快速的方法来完成此任务。这是它的简化版本。 数据告诉您眼睛在每个时间点正在查看的位置以及我们正在查看的每个文件。 X
我是新手,想为计时器或其他设备选择提示音。 如何打开此列表,以选择其中一种声音? Alert sound list 最佳答案 您将无法在应用中使用系统声音。 但是,您可以包括自己的声音文件,并将其显示
我编写了以下代码来构建具有顺序字符串的数组。 它的工作方式与我预期的一样,但我希望它能更快地运行。有没有更有效的方法在PowerShell中产生我想要的结果? 我是PowerShell的新手,非常感谢
我有一个包含一些非唯一行的矩阵,例如: x 尝试 y <- rle(apply(x, 1, paste, collapse = " ")) # y$lengths is the vector con
我的函数“keyboardWillShown”有问题。所以我想要的是菜单打开时,菜单正好出现在键盘上方。它可以在Iphone 8 plus,8、7、6上完美运行。但是,当我在模拟器上运行Iphone
我正在尝试通过Swift 5中的HTTP get方法从API提取数据。它在启动时成功加载了数据,但是当我刷新页面时,它说“索引超出范围”,这是因为数据是不再会在我的日志中读取,因此索引中没有任何内容。
我想做什么: 从我的数据库中获取时间戳并将其转换为用户的时区。 我的代码: let tryItNow = "\(model.timestampName)" let format = D
给定字体名称和字体大小,如何查找字符串的宽度(CGFloat)? (目标是将UIView的宽度设置为足以容纳字符串的宽度。) 我有两个字符串:一个重复“1”,重复36次,另一个重复“M”,重复36次。
我正在尝试解析此JSON ["Items": ( { AccountBalance = 0; AlphabetType = 3; Description = "\U0631\U
我在UINavigationBar内放置了一个UILabel。 我想根据navigationBar的高度增加该标签的字体大小。当navigationBar很大时,我希望字体大小更大;当滚动并缩小nav
我想将用户输入限制为仅有效数字并使用以下内容: func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, rep
目前我有一个包含超过 100.000 张图像的数据库,它们大小不一或类似,但我想为我的公司制作以下内容: 我插入/上传一张图片,系统返回最有可能相同的图片。我不知道使用什么算法,但它需要快速。我可以预
在我的 swift 项目中,我有一个按钮,我想在标签上打印按下该按钮的时间。 如何解决这个问题? 最佳答案 添加到DHEERAJ的答案中,您只需在func press(sender: UIButton
我必须发表评论,尝试在解析中导入数组。然而,有一个问题。 当我尝试从 Parse 加载数组时,我的输出是 ("Blah","Blah","Blah")这是一个元组...而不是一个数组 TT... 如何
我的应用程序有一个名为 MyDevice 的类,我用它来与硬件通信。该硬件是可选的,实例变量也是可选的: var theDevice:MyDevice = nil 然后,在应用程序中,我必须初始化设备
我是一名优秀的程序员,十分优秀!