我正在尝试在图像上创建标记,以允许用户选择颜色、标记特征等。最终我希望通过 opencv 获得相应的图像像素以供进一步使用。
我在触摸下获得预期的颜色时遇到了很多麻烦,有时它会返回像洋红色这样的颜色,而这些颜色甚至不在示例图像中。
我很确定问题在于我如何将触摸位置转换为传递给 read_pixel 函数的值。
我尝试了许多不同的解决方案但没有成功,所以我认为我在这里缺少一些东西。
主要.py
from kivy.app import App
from kivy.properties import ListProperty, ObjectProperty
from kivy.uix.image import AsyncImage
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.widget import Widget
from kivy.uix.screenmanager import ScreenManager, Screen
class Marker(Widget):
selected_color = ListProperty([0,1,0])
def __init__(self, **kwargs):
super(Marker, self).__init__(**kwargs)
self.selected_pos = None
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
print("Touched at Marker: {0}".format(touch.spos))
def on_touch_move(self, touch):
self.set_position_from_touch(touch.spos)
def set_position_from_touch(self, spos):
# print("touch: {0}".format(touch))
self.image = self.parent.parent.image
x = spos[0] * self.image.width
y = spos[1] * self.image.height
# setting position of the widget relative to touch
self.pos = (x-self.width/2, y-self.height*(2/3))
# self.pos = (x, y)
print("widget position : {0}".format(self.pos))
# converting widget position to pixel(row, column of
selected_pixel = self.image.to_row_col(self.pos)
print("selected Pixel: {0}".format(selected_pixel))
try:
self.selected_color = self.image._coreimage.read_pixel(
selected_pixel[0],
selected_pixel[1])
# this skips conversion and just uses pos
# self.pos[0],
# self.pos[1])
except IndexError:
print("position out of range")
class MarkerManager(RelativeLayout):
def __init__(self, **kwargs):
super(MarkerManager, self).__init__(**kwargs)
self.marker_mode = None
self.features = []
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
child_touched = False
print("Touched: {0}".format(touch))
if self.children:
for child in self.children[:]:
if child.collide_point(touch.pos[0], touch.pos[1]):
child_touched = True
child.dispatch('on_touch_down', touch)
if not child_touched:
print("Touched only Image at: {0}".format(touch.spos))
marker = Marker()
self.features.append(marker)
self.add_widget(marker)
marker.set_position_from_touch(touch.spos)
class SelectedImage(AsyncImage):
def __init__(self, **kwargs):
super(SelectedImage, self).__init__(**kwargs)
self.allow_stretch=True
self.keep_ratio=False
def to_row_col(self, pos):
pixels_x = self._coreimage.width
pixels_y = self._coreimage.height
pixel_x = (pos[0] / self.width) * pixels_x
# pixel_y = (pos[1] / self.height) * self.pixels_y
pixel_y = (1 - (pos[1] / self.height)) * pixels_y
# should correspond to row column of image
return [int(pixel_x), int(pixel_y)]
class ImageScreen(Screen):
image = ObjectProperty()
manager = ObjectProperty()
def __init__(self, **kwargs):
super(ImageScreen, self).__init__(**kwargs)
class PointsSelectorApp(App):
def build(self):
return ImageScreen()
if __name__ == "__main__":
PointsSelectorApp().run()
Run Code Online (Sandbox Code Playgroud)
点选择器.kv
<ImageScreen>:
image: image_id
manager: manager_id
SelectedImage:
id: image_id
source: "rainbow_checkerboard.jpg"
keep_data: True
MarkerManager:
id: manager_id
<Marker>:
size_hint: None, None
size: "40dp", "40dp"
canvas:
Color:
rgb: self.selected_color
Ellipse:
pos: self.pos[0]+self.width/4, self.pos[1]+self.height/3
# pos: self.pos[0], self.pos[1]
size: self.width*.6, self.height*.6
Run Code Online (Sandbox Code Playgroud)
这是我一直用来测试“rainbow_checkerboard.jpg”的图像
我相信这是 Kivy 本身的一个错误。特别是我认为kivy/core/image/__init__.py 的第 901 行
index = y * data.width * size + x * size
raw = bytearray(data.data[index:index + size])
color = [c / 255.0 for c in raw]
Run Code Online (Sandbox Code Playgroud)
是错的。它应该是
index = y * data.rowlength + x * size
Run Code Online (Sandbox Code Playgroud)
反而。
这里重要的是,出于性能原因,内存中的位图图像在 4 字节地址上对齐。因此存在一个显式data.rowlength字段。通常这条线工作得很好,因为图像通常对齐得很好,因此data.rowlength = data.width * size。但你的特定图像是不同的:它使用 3 字节RGB格式(无 alpha),并且其宽度是奇数561,即data.width * size= 1683,因此data.rowlength应该四舍五入为1684,它实际上是,但该代码没有考虑到它。这意味着您通常会从两个连续像素读取颜色,并且 RGB 分量随机旋转。
此外,由于您对图像使用 JPEG 格式,因此“单元格”之间的边界并不严格。如果您非常用力放大,您可以看到一些压缩伪影,例如左下角的这些伪影。
这些伪影因上述随机颜色分量旋转错误而倍增,给您带来非常奇怪(看似不存在)的颜色。
可能的解决方法
kivy/core/image/__init__.py文件(我尝试过,似乎工作正常)。| 归档时间: |
|
| 查看次数: |
882 次 |
| 最近记录: |