gpt4 book ai didi

python - 为什么 kivy read_pixel 没有返回预期的颜色?

转载 作者:太空宇宙 更新时间:2023-11-04 00:35:22 24 4
gpt4 key购买 nike

我正在尝试在图像上创建标记,允许用户选择颜色、标记特征等。最终我希望通过 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()

点选择器.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

这是我用来测试“rainbow_checkerboard.jpg”的图片

my test image

最佳答案

我认为这是 Kivy 本身的错误。特别是我认为 line 901 at the kivy/core/image/__init__.py

    index = y * data.width * size + x * size
raw = bytearray(data.data[index:index + size])
color = [c / 255.0 for c in raw]

错了。应该是

    index = y * data.rowlength + x * size

相反。

这里重要的是,出于性能原因,内存中的位图图像按 4 字节地址排列。因此,有一个显式的 data.rowlength 字段。通常该行工作正常,因为图像通常对齐良好,因此 data.rowlength = data.width * size。但是你的特定图像是不同的:它使用 3 字节 RGB 格式(无 alpha)并且它的宽度是奇数 561data.width * size = 1683 所以 data.rowlength 应该四舍五入到 1684,它实际上是但代码没有考虑到它.这意味着您经常从两个连续像素读取颜色,并且 RGB 分量随机旋转。

此外,由于您对图像使用 JPEG 格式,因此“单元格”之间的边界并不是很严格。如果您非常用力地放大,您会在左下角附近看到一些压缩伪影,例如这些。

JPEG Artifacts

那些被前面提到的随机颜色分量旋转错误所叠加的伪影给你带来了非常奇怪的(看似不存在的)颜色。

可能的解决方法

  1. 更改您的图像,使其在内存中预先对齐并且错误不会影响您(例如使用 4 的倍数作为宽度)
  2. 向 Kivy 提交错误甚至拉取请求并等待其修复
  3. 在本地修补 kivy/core/image/__init__.py 文件(我试过了,它似乎工作正常)。

关于python - 为什么 kivy read_pixel 没有返回预期的颜色?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44292621/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com