import bpy
import math
from abc import ABC, abstractmethod
import numpy as np
[docs]
def findNearestColor(sampleColor, colorBar):
central_column_colors = []
for color in colorBar:
central_column_colors.append(color[1])
central_column_colors = np.array(central_column_colors)
sampleColor = np.array(sampleColor, dtype=np.float32)
distances = np.sum((central_column_colors - sampleColor) ** 2, axis=1)
if distances.min() > 0.5:
return 0.0
position = np.argmin(distances)
return colorBar[position][0]
[docs]
class Image(ABC):
def __init__(self, imageName):
self._image = bpy.data.images.get(imageName)
self._width, self._height = self._image.size
self._pixels = list(self._image.pixels)
self._center = [self._width / 2.0, self._height / 2.0]
[docs]
class Spot(Image):
def __init__(self, *, laserSpot):
super().__init__('spot')
self._maxRadius = laserSpot.spot_size / 2.0
[docs]
def getColor(self, x, y):
deltaX = self._width / 2.0 * x / self._maxRadius
deltaY = self._height / 2.0 * y / self._maxRadius
x = int(self._center[0] + deltaX)
y = int(self._center[1] - deltaY)
if x < 0 or x > self._width:
return (0, 0, 0, 0)
if y < 0 or y > self._height:
return (0, 0, 0, 0)
index = (y * self._width + x) * 4
index = int(index)
index = index - (index % 4)
try:
r = self._pixels[index]
g = self._pixels[index + 1]
b = self._pixels[index + 2]
a = self._pixels[index + 3]
except Exception:
return (0, 0, 0, 0)
return (r, g, b, a)
[docs]
def getPixelIndex(self, x, y):
deltaX = self._width / 2.0 * x / self._maxRadius
deltaY = self._height / 2.0 * y / self._maxRadius
x = int(self._center[0] + deltaX)
y = int(self._center[1] - deltaY)
return y * self._width + x
[docs]
class ColorBar(Image):
def __init__(self, *, bottomLeftValue, topRightValue):
super().__init__('colorBar')
self._bottomLeftValue = bottomLeftValue
self._topRightValue = topRightValue
if self._height > self._width:
self._delta = self._width
self._length = self._height
delta = 0.035
self._data = []
x = 0.000
while x <= 1.0:
color = self.getColor(x)
value = self._bottomLeftValue + (self._topRightValue - self._bottomLeftValue) * x
self._data.append((value, color))
x += delta
[docs]
def getColor(self, x):
if x < 0.0 or x > 1.0:
return (0, 0, 0, 0)
x = x * self._length
index = x * self._delta + 0.5 * self._delta
if index > self._length * self._delta:
index = self._length * self._delta - 0.5 * self._delta
index *= 4
index = int(index)
index = index - (index % 4)
try:
r = self._pixels[index]
g = self._pixels[index + 1]
b = self._pixels[index + 2]
a = self._pixels[index + 3]
except Exception:
return (0, 0, 0, 0)
return (r, g, b, a)
[docs]
class ImageSpot:
def __init__(self, *, laserSpot):
self._spot = Spot(laserSpot=laserSpot)
self._colorBar = ColorBar(
bottomLeftValue=laserSpot.first_treshold,
topRightValue=laserSpot.second_treshold
)
self._values = []
for index in range(0, self._spot._width * self._spot._height):
cindex = index * 4
r = self._spot._pixels[cindex]
g = self._spot._pixels[cindex + 1]
b = self._spot._pixels[cindex + 2]
a = self._spot._pixels[cindex + 3]
spotColor = (r, g, b, a)
value = findNearestColor(spotColor, self._colorBar._data)
self._values.append(value)
pass
[docs]
def getValue(self, *, x=0, y=0):
index = self._spot.getPixelIndex(x, y)
try:
value = self._values[index]
except Exception:
value = 0.0
return value
@property
def maxRadius(self):
return self._spot._maxRadius
@property
def colorBar(self):
return self._colorBar._data