Improve CPU time of conditional statement
我写了一份if-elif声明,我认为这不是很有效:
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 | first_number = 1000 second_number = 700 switch = { 'upperRight': False, 'upperLeft': False, 'lowerRight': False, 'lowerLeft': False, 'middleLeft': False, 'middleRight': False, 'upperMiddle': False, 'lowerMiddle': False, 'middle': False } for i in range(first_number): for j in range(second_number): if pixel_is_black: if i <= int(first_number/3) and j <= int(second_number/3): switch['upperLeft'] = True elif i <= int(first_number/3) and int(second_number/3) < j <= int(2*second_number/3): switch['middleLeft'] = True elif i <= int(first_number/3) and j > int(2*second_number/3): switch['lowerLeft'] = True elif int(first_number / 3) <= i < int(2 * first_number / 3) and j < int(second_number / 3): switch['upperMiddle'] = True elif int(first_number / 3) <= i < int(2 * first_number / 3) and int(second_number / 3) < j <= int(2 * second_number / 3): switch['middle'] = True elif int(first_number / 3) <= i < int(2 * first_number / 3) and j >= int(2 * second_number / 3): switch['lowerMiddle'] = True elif i >= int(2 * first_number / 3) and j <= int(2 * second_number / 3): switch['upperRight'] = True elif i >= int(2 * first_number / 3) and int(second_number / 3) < j <= int(2 * second_number / 3): switch['middleRight'] = True elif i >= int(2 * first_number / 3) and j >= int(2 * second_number / 3): switch['lowerRight'] = True for i in switch: if(switch[i] == True): print(i) |
如你所见,声明看起来很难看。因为数字很大,所以执行几乎需要2秒钟。在循环中,我将遍历图像的像素。在if-elif语句中,如果像素在该区域为黑色,我将图像分成9个部分,并打印相应的数字。
有什么方法可以降低CPU时间吗?
我试过这个答案,但我的陈述条件不同。
谢谢您。
因为你使用的是图像和numpy,我认为最简单的方法就是将图像分割成块,看看这些块中是否有像素是黑色的。例如,假设我有一个边缘图像,中间没有任何黑色像素,如下所示:
我们可以使用列表理解将图像转换为块:
1 2 3 4 5 6 | h, w = img.shape[:2] bh, bw = h/3, w/3 bw_ind = [0, int(bw), 2*int(bw), w] bh_ind = [0, int(bh), 2*int(bh), h] blocks = [img[bh_ind[i]:bh_ind[i+1], bw_ind[j]:bw_ind[j+1]] for i in range(3) for j in range(3)] |
号
号
号
现在,为了简单一点,我们可以按照块所在的顺序列出列表字典中的键;这样,
1 2 3 4 5 | switch_list = [ 'upperLeft', 'upperMiddle', 'upperRight', 'middleLeft', 'middle', 'middleRight', 'lowerLeft', 'lowerMiddle', 'lowerRight' ] |
最后要做的就是找到每个块中的黑色像素。所以我们要通过9个块(使用循环),然后将块内的值与我们感兴趣的任何颜色进行比较。如果您有一个3通道8位图像,那么黑色通常在每个通道中用一个
1 2 | >>> pixel == [0,0,0] [True, True, True] |
只有当所有三个值都匹配时,像素才是黑色的,所以我们可以在结果上使用
1 2 | >>> (pixel == [0,0,0]).all() True |
所以这是我们的指示器,一个像素是黑色的。但我们需要检查是否有任何像素是黑色在我们的块。为了简单起见,我们先来看看单通道图像。假设我们有阵列
1 | M = np.array([[0,1], [2,3]]) |
如果我们在这里使用逻辑比较,
1 2 | >>> M == 5 array([[False, False] [False, False]]) |
在我们的例子中,我们不需要知道每个比较,我们只想知道块中的单个像素是否是黑色的,所以我们只需要一个布尔值。我们可以用
1 2 | >>> (M == 5).any() False |
因此,我们需要结合这两个操作;我们将确保所有值与我们感兴趣的颜色(
1 | black_pixel_in_block = [(block==[0,0,0]).all(axis=2).any() for block in blocks] |
注意:
1 2 | for i in range(len(switch_list)): switch[switch_list[i]] = black_pixel_in_block[i] |
最后,
1 2 3 4 5 6 7 8 9 10 | >>> print(switch) {'upperRight': True, 'upperLeft': True, 'lowerRight': True, 'lowerLeft': True, 'middleLeft': True, 'middleRight': True, 'upperMiddle': True, 'lowerMiddle': True, 'middle': False} |
仅在这里进行的操作在(21402870)图像上花费了约0.1秒。
在同一行中,您可以首先创建一个由
在这种情况下,您可以避免整个
1 2 3 4 5 6 7 | for i in range(first_number): horizontal_third = i * 3 // first_number for j in range(second_number): if pixel_is_black(i, j): # I assume this depends on the coordinates in some way vertical third = j * 3 // second_number key = str(horizontal_third * 3 + vertical_third + 1) # use int keys? zero-index? switch[key] = True |
请注意,给一些变量指定更有意义的名称可能是个好主意。
如果您愿意稍微更改