提高Numpy的循环速度

时间:2020-07-28 22:43:51

标签: python numpy opencv

我试图找到最接近RGB值(0,0,255)的像素。我正在尝试使用3D毕达哥拉斯(Pythagoras)计算来计算RGB值中的像素到该值的距离,将它们添加到列表中,然后返回具有最小距离的值的X和Y坐标。这就是我所拥有的:

# import the necessary packages
import numpy as np
import scipy.spatial as sp
import matplotlib.pyplot as plt
import cv2
import math
from PIL import Image, ImageDraw, ImageFont

background = Image.open("test.tif").convert('RGBA')
png = background.save("test.png")

retina = cv2.imread("test.png")
#convert BGR to RGB image
retina = cv2.cvtColor(retina, cv2.COLOR_BGR2RGB)

h,w,bpp = np.shape(retina)

min1_d = float('inf')
min1_coords = (None, None)

min2_d = float('inf')
min2_coords = (None, None)


for py in range(0,h):
    for px in range (0,w):
        r = retina[py][px][0]
        g = retina[py][px][1]
        b = retina[py][px][2]
        d = math.sqrt(((r-0)**2) + ((g-0)**2) + ((255-b)**2))
        print(str(r) + "," + str(g) + "," + str(b) + ",," + str(px) + "," + str(py) + ",," + str(d))
        if d < min1_d:
            min2_d = min1_d
            min2_coords = min1_coords
            
            min1_d = d
            min1_coords = (px, py)
        elif d < min2_d: # if it's not the smallest, check if it's the second smallest
            min2_d = d
            min2_coords = (px, py)

print(min1_coords, min2_coords)

width, height = background.size
x_max = int(width)
y_max = int(height)

img = Image.new('RGBA', (x_max, y_max), (255,255,255,0))
draw = ImageDraw.Draw(img)
draw.point(min1_coords, (0,0,255))
draw.point(min2_coords, (0,0,255))

foreground = img
background.paste(foreground, (0, 0), foreground)
foreground.save("test_bluer.png")
background.save("test_bluer_composite.png")

如何加快我的for循环?我相信这个答案是正确的,但是我不确定如何在切片as this answer切片时实现px和py变量。

3 个答案:

答案 0 :(得分:1)

您可以通过向量化for循环来加快代码的速度:

    r = retina[:,:,0]
    g = retina[:,:,1]
    b = retina[:,:,2]
    d = np.sqrt(r**2 + g**2 + (255-b)**2)

您可以使用以下方法找到最小值的坐标:

    min_coords = np.unravel_index(np.argmin(d), np.shape(d))

如果要查找第二个最小距离,只需将前一个最小距离更改为更大的距离即可:

    d[min_coords[0],min_coords[1]] = np.inf
    min_coords = np.unravel_index(np.argmin(d), np.shape(d))
    # min_coords now has the second smallest distance

答案 1 :(得分:0)

这是Python / OpenCV中的一种方法。

  • 阅读输入内容
  • 定义颜色(纯蓝色)
  • 创建所需颜色的图像
  • 计算代表均方根差的图像
  • 阈值rmse图像
  • 获取所有白色像素的坐标

输入:

enter image description here

import cv2
import numpy as np

# read image
img = cv2.imread('red_blue2.png')

# reference color (blue)
color = (255,0,0)

# create image the size of the input, but with blue color
ref = np.full_like(img, color)

# compute rmse difference image
diff = cv2.absdiff(img, ref)
diff2 = diff*diff
b,g,r = cv2.split(diff)
rmse = np.sqrt( ( b+g+r )/3 )

# threshold for pixels within 1 graylevel different
thresh = cv2.threshold(rmse, 1, 255, cv2.THRESH_BINARY_INV)[1]

# get coordinates
coords = np.argwhere(thresh == 255)
for coord in coords:
    print(coord[1],coord[0])


# write results to disk
cv2.imwrite("red_blue2_rmse.png", (20*rmse).clip(0,255).astype(np.uint8))
cv2.imwrite("red_blue2_thresh.png", thresh)

# display it
cv2.imshow("rmse", rmse)
cv2.imshow("thresh", thresh)
cv2.waitKey(0)

RMSE图像(以20倍的亮度缩放以进行查看):

enter image description here

阈值rmse图像:

enter image description here

坐标:

127 0
128 0
127 1
128 1
127 2
128 2
127 3
128 3
127 4
128 4
127 5
128 5
127 6
128 6
127 7
128 7
127 8
128 8
127 9
128 9
127 10
128 10
127 11
128 11
127 12
128 12
127 13
128 13
127 14
128 14
127 15
128 15
127 16
128 16
127 17
128 17
127 18
128 18
127 19
128 19
127 20
128 20
127 21
128 21
127 22
128 22
127 23
128 23
127 24
128 24
127 25
128 25
127 26
128 26
127 27
128 27
127 28
128 28
127 29
128 29
127 30
128 30
127 31
128 31
127 32
128 32
127 33
128 33
127 34
128 34
127 35
128 35
127 36
128 36
127 37
128 37
127 38
128 38
127 39
128 39
127 40
128 40
127 41
128 41
127 42
128 42
127 43
128 43
127 44
128 44
127 45
128 45
127 46
128 46
127 47
128 47
127 48
128 48
127 49
128 49

答案 2 :(得分:0)

如前所述,从数组,正方形,平均(或总和)像素rgb值中减去rgb值,得到最小值。

这是我的变体:

import numpy

rgb_value = numpy.array([17,211,51])
img = numpy.random.randint(255, size=(1000,1000,3),dtype=numpy.uint8)

img_goal = numpy.average(numpy.square(numpy.subtract(img, rgb_value)), axis=2)

result = numpy.where(img_goal == numpy.amin(img_goal))
result_list = [result[0].tolist(),result[1].tolist()]
for i in range(len(result_list[0])):
    print("RGB needed:", rgb_value)
    print("Pixel:", result_list[0][i], result_list[1][i])
    print("RGB gotten:", img[result_list[0][i]][result_list[1][i]])
    print("Distance to value:", img_goal[result_list[0][i]][result_list[1][i]])

可以有多个具有相同值的结果。