【问题标题】:How do I get coordinates of boolean 'True' from pd.dataframe?如何从 pd.dataframe 获取布尔值“真”的坐标?
【发布时间】:2020-02-16 19:57:32
【问题描述】:

我有一个 png,我把它变成了 pd.DataFrame,其中包含布尔值。对于白色像素,我得到“假”,而对于黑色像素,我得到“真”。我想生成 DXF 图。为此,我正在尝试获取数据框中每个“真”的坐标,以便稍后将它们连接起来画线。

这是我目前拥有的代码:

from PIL import Image
import numpy as np
import pandas as pd

img = Image.open('/home/sinushas/Downloads/Brezynio_Konvertavimas/test.png')
thresh = 200
fn = lambda x : 255 if x > thresh else 0
r = img.convert('L').point(fn, mode='1')
r.save('/home/sinushas/Downloads/Brezynio_Konvertavimas/test_converted.png')

im = Image.open('/home/sinushas/Downloads/Brezynio_Konvertavimas/test_converted.png')
im2arr = np.array(im) # im2arr.shape: height x width x channel

df = pd.DataFrame(im2arr)
df = (df == False) 

这是生成的 pd.Dataframe:

    0   1   2   3   4   5   6   7   8   9
0   False   False   False   False   False   False   False   False   False   False
1   False   False   False   False   False   False   False   False   False   False
2   False   False   True    True    True    True    True    True    False   False
3   False   False   False   False   True    True    False   False   False   False
4   False   False   False   False   True    True    False   False   False   False
5   False   False   False   False   True    True    False   False   False   False
6   False   False   False   False   True    True    False   False   False   False
7   False   False   False   False   False   False   False   False   False   False
8   False   False   False   False   False   False   False   False   False   False
9   False   False   False   False   False   False   False   False   False   False

我希望得到以下坐标: (2:3),(2:4),(2:5),(2:6),(2:7),(2:8),(3:5),(3:6),(4 :5),(4:6),(5:5),(6:6),(6:5),(6:6)

我还没有找到可以从 Dataframe 中获取任何坐标的工作代码。 我试过的东西:

result = im2arr.where('True')

df.sort_index() 

res = [i for i, val in enumerate(df) if val]

感谢任何提示。

【问题讨论】:

    标签: python python-3.x pandas dataframe coordinates


    【解决方案1】:

    使用np.where:

    coord = np.where(df)
    
    coordinates = [(x,y) for x, y in zip(coord[0], coord[1])]
    

    输出

    [(2, 2),
     (2, 3),
     (2, 4),
     (2, 5),
     (2, 6),
     (2, 7),
     (3, 4),
     (3, 5),
     (4, 4),
     (4, 5),
     (5, 4),
     (5, 5),
     (6, 4),
     (6, 5)]
    

    【讨论】:

      【解决方案2】:

      DataFrame.stack

      创建boolean indexing

      df2=df.stack()
      coordinates=[*df2[df2].index]
      

      #print(coordinates)
      [(2, 2),
       (2, 3),
       (2, 4),
       (2, 5),
       (2, 6),
       (2, 7),
       (3, 4),
       (3, 5),
       (4, 4),
       (4, 5),
       (5, 4),
       (5, 5),
       (6, 4),
       (6, 5)]
      

      【讨论】:

        【解决方案3】:

        您不需要pandas。而且您不必再次阅读它。你甚至可以在.point(fn, mode='L')中使用L

        r = img.convert('L').point(fn, mode='1')
        r.save(...)
        
        data = np.where(r)          # [[y1,y2,...], [x1,x2,...], ]
        points = list(zip(*data))   # [[y1,x1], [y2,x2], ...]
        
        print(points)
        

        您可以直接在r 上使用where() 来获取[[y1,y2,...], [x1,x2,...]] 的列表。

        然后您可以使用zip() 来创建对[y1, x1][y2,x2] 等。

        编辑:对于其他像素,您可以使用~ 否定r 中的值

        data = np.where(~r)          # other pixels
        

        数组适用于坐标(row, columns),这意味着(y, x) - 就像您预期的数据(2,3), (2,4) - 但如果您需要(x, y),请使用:

        points = list(zip(data[1], data[0]))
        

        最终

        points = [(x,y) for y,x in zip(*data)]
        

        编辑:你甚至不需要.point()

        from PIL import Image
        import numpy as np
        
        img = Image.open('image.png').convert('L')
        
        arr = np.array(img)
        
        #data = np.where( arr > 200 )    # for white pixels
        #data = np.where( ~(arr > 200) ) # for black pixels too
        data = np.where(arr < 200) # for black pixels
        
        points_y_x = list(zip(*data))
        points_x_y = list(zip(data[1], data[0]))
        
        print(points_y_x)
        print(points_x_y)
        

        【讨论】:

        • 如果我从编辑中使用你的代码,它似乎给了我图像中的所有坐标,颜色为白色而不是黑色
        • 当我测试您的代码时,它会为白色像素提供True,因此我的代码也为相同元素提供坐标。但是您可以使用&lt; 200 而不是&gt; 200 来获得黑色而不是白色。
        • 在第一个版本中,您可以使用 ~ 否定值 - data = np.where(~r)
        • 我看到了问题。我没有使用DataFrame,我错过了你的最后一行df = (df == False),它否定了DataFrame 中的值。所以你也必须在我的代码中使用~r 来对值进行导航。在第二个示例中,使用 ~(arr &gt; 200) 而不是 arr &gt; 200 或简单地使用 arr &lt; 200
        • 谢谢你给我解释,我试试看!
        【解决方案4】:

        np.nonzero:

        [(x,y) for x,y in zip(*np.nonzero(df.values))]
        

        输出:

        [(2, 2),
         (2, 3),
         (2, 4),
         (2, 5),
         (2, 6),
         (2, 7),
         (3, 4),
         (3, 5),
         (4, 4),
         (4, 5),
         (5, 4),
         (5, 5),
         (6, 4),
         (6, 5)]
        
        ​
        

        【讨论】:

          猜你喜欢
          • 2015-04-01
          • 1970-01-01
          • 2021-12-17
          • 2015-11-12
          • 2012-12-06
          • 1970-01-01
          • 2016-07-08
          • 2012-02-01
          • 1970-01-01
          相关资源
          最近更新 更多