【问题标题】:How to find a 2x2 object in a 2D list?如何在 2D 列表中找到 2x2 对象?
【发布时间】:2017-03-02 14:00:41
【问题描述】:

我有一个必须在学校完成的练习,但我有点卡住了。 我必须编写一个函数来告诉你照片上是否有一张脸,通过照片我们可以想象一个 2D 列表,所以一个包含更多列表的列表来创建一个 2 维对象。面由 2x2 正方形表示,其中包含单词 face,这些字母可以是随机顺序。如下图一、二:

还可以有更多的面,只要单词 face 在整个 2Dlist 中至少显示一次,它就应该返回 True。

问题是字母不能在一行或一列中,如图 III 所示。我真的不知道如何制定一个可以消除这种情况的条件。到目前为止,我知道如何找出所有字母是否都在该 2Dlist 中,并且我消除了只有一行或一列的可能性,如图 IV 所示。和V..

这是我目前所拥有的:

def is_face_on_photo(photo):
    list2D = photo
    faces = ['f','a','c','e']
    newlist = []
    for list in list2D:
        for letter in list:
            newlist.append(letter)
    if 'f' in newlist and 'a' in newlist and 'c' in newlist and 'e' in newlist and (faces not in list2D) and (len(list2D) >= 2) and (len(list2D[0]) >= 2):
        print True
    else:
        print False
 pass

我是 python 新手,所以如果能得到任何帮助,我将不胜感激 :) 非常感谢

【问题讨论】:

  • 我认为图三是无效的,因为它包含的两个“脸”方块相互重叠。
  • “他的问题是字母不能在一行或一列中,如图三所示..”你是指图四吗?
  • 您的图片中哪些有效,哪些无效?
  • I. II.三。有效

标签: python list face-detection


【解决方案1】:

逐个元素地搜索每一行,然后是下一行,以此类推,从左到右,再向下,直到找到 F、A、C 或 E。

当你这样做时,由于你是从左到右和从上到下检查,你可以假设你已经找到了一个潜在的“FACE”的左上角。所以检查右边的字母、下面的字母和右下角的字母是否满足 FACE 的其余部分。

如果是这样,你就完成了。如果没有,请继续。

编辑:这是一个有点罗嗦的版本。我还没有测试过,但就是这个想法。

def is_face_on_photo(photo):
    found = False

    for row,photo_row in enumerate(photo):
        for col,letter in enumerate(photo_row):

            if (letter in "face") and col + 1 < len(photo_row) and row + 1 < len(photo):
                found = True  # Until proven otherwise

                num_found = {"f":0, "a":0, "c":0, "e":0}

                right_letter = photo_row[col + 1]
                below_letter = photo[row + 1][col]
                below_right_letter = photo[row + 1][col + 1]

                letters = [letter, right_letter, below_letter, below_right_letter]

                # Could replace with something like defaultdict
                for let in letters:
                    if let in num_found:
                        num_found[let] += 1

                # Would need to change this slightly if the letters of "face" had 
                # any repetitions, like two "a"s or something
                for let in "face":
                    if num_found[let] == 0:
                        found = False
                        break

            if found:
                break

        if found:
            break

    return found

【讨论】:

  • 非常感谢!这完全解决了我的问题,我不知道您可以使用这样的行和列。
【解决方案2】:

使用与另一个答案中描述的方法有些相似的方法,这是一个应该可以工作的实现。它将遍历每个单元格,如果该单元格在“面”中包含一个字母,它将继续检查右侧的三个单元格、下方的三个单元格以及它是右上角成员的正方形。

请注意,这不是最有效的方法:以前尝试的信息(可能会阻止大多数此类尝试)不会被保留。

def is_face_on_photo(arr):
    word = set('face')
    num_rows = len(arr)
    num_cols = len(arr[0])
    for y, row in enumerate(arr):
        for x, cell in enumerate(row):
            if cell in word:
                # horizontal?
                if x + 3 < num_cols and set(row[x:x+4]) == word:
                    return True
                # vertical
                if y + 3 < num_rows and set(arr[i][x] for i in range(y, y + 4)) == word:
                    return True
                # square
                if x + 1 < num_cols and y + 1 < num_cols and set(arr[y][x:x+2] + arr[y+1][x:x+2]) == word:
                    return True
    return False

    arr = [
        ['x', 'x', 'x', 'x'],
        ['x', 'f', 'c', 'x'],
        ['x', 'a', 'e', 'x'],
        ['x', 'x', 'x', 'x']
    ]

    print (is_face_on_photo(arr)) # True

【讨论】:

    【解决方案3】:

    这是扫描二维列表的一种方法。

    我们使用内置的zip 函数从照片中获取相邻行对,并再次使用zip 从当前行对中获取相邻单元格对。这为我们提供了 2x2 正方形中的 4 个单元格。我们还使用内置的enumerate 函数为我们提供当前 2x2 正方形左上角的 x,y 索引。

    我们将正方形中的字母放入一个集合中,这样我们就可以快速测试它是否等于包含“face”字母的集合。但我们还需要确保我们找到的任何人脸都不会与我们已经找到的人脸重叠。为此,我们维护了一个集合 found,用于跟踪我们找到的每个人脸的 x、y 索引。

    更新

    这是此代码的更好版本;以前的版本不处理包含重叠面和非重叠面的照片。这个版本维护了另一个集合bad,它跟踪与其他人脸重叠的人脸。

    all_data = [
        [
            ['x', 'x', 'x', 'x'],
            ['x', 'f', 'a', 'x'],
            ['x', 'c', 'e', 'x'],
            ['x', 'x', 'x', 'x'],
        ],
        [
            ['c', 'a', 'x', 'x'],
            ['f', 'e', 'x', 'x'],
            ['x', 'x', 'x', 'x'],
            ['x', 'x', 'x', 'x'],
        ],
        [
            ['c', 'a', 'f', 'x'],
            ['f', 'e', 'c', 'x'],
            ['x', 'x', 'x', 'x'],
            ['x', 'x', 'x', 'x'],
        ],
        [
            ['c', 'a', 'f', 'x'],
            ['f', 'e', 'c', 'x'],
            ['x', 'c', 'e', 'x'],
            ['x', 'f', 'a', 'x'],
        ],
        [
            ['x', 'a', 'x', 'x'],
            ['f', 'e', 'x', 'x'],
            ['x', 'x', 'x', 'x'],
            ['x', 'x', 'x', 'x'],
        ],
        [
            ['c', 'a', 'x', 'x', 'x', 'x'],
            ['f', 'e', 'c', 'a', 'f', 'e'],
            ['f', 'e', 'e', 'f', 'a', 'c'],
            ['a', 'c', 'x', 'x', 'x', 'x'],
        ],
    ]
    
    def show(a):
        print('\n'.join(''.join(row) for row in a))
    
    face = set('face')
    
    def is_face_on_photo(photo):
        ''' Return the number of valid faces found in photo '''
        found = set()
        bad = set()
        # Get pairs of adjacent rows
        for y, (row0, row1) in enumerate(zip(photo, photo[1:])):
            # Get pairs of adjacent cells from the pair of rows
            for x, t in enumerate(zip(row0, row0[1:], row1, row1[1:])):
                if set(t) == face:
                    found.add((x, y))
                    # See if it overlaps any existing faces
                    newbad = found.intersection({(x-1, y), (x, y-1), (x-1, y-1)})
                    if newbad:
                        bad.update(newbad)
                        bad.add((x, y))
        return len(found) - len(bad)
    
    for photo in all_data:
        show(photo)
        print(is_face_on_photo(photo), '\n')
    

    输出

    xxxx
    xfax
    xcex
    xxxx
    1 
    
    caxx
    fexx
    xxxx
    xxxx
    1 
    
    cafx
    fecx
    xxxx
    xxxx
    0 
    
    cafx
    fecx
    xcex
    xfax
    1 
    
    xaxx
    fexx
    xxxx
    xxxx
    0 
    
    caxxxx
    fecafe
    feefac
    acxxxx
    4 
    

    【讨论】:

      猜你喜欢
      • 2014-12-09
      • 1970-01-01
      • 1970-01-01
      • 2022-01-23
      • 1970-01-01
      • 2021-06-23
      • 2019-07-10
      • 2014-12-18
      • 2012-11-11
      相关资源
      最近更新 更多