파이썬 긴 if문을 간단히 표현하기

조회수 1238회
import numpy as np
import cv2 as cv

img = cv.imread('dp.png')

img_h = img.shape[0]
img_w = img.shape[1]
img_bpp = img.shape[2]

print(img_h, img_w, img_bpp)

blue = (255,0,0)
white = (255,255,255)

a = 450
b = 0
c = list()
d = list()
e = 0

bthick = 12


 for b in range(0,img_h-12):
   if (img[b,a] == [255,255,255]).all() and \
(img[b+1,a] != [255,255,255]).all() and \
(img[b+2,a] != [255,255,255]).all() and \
(img[b+3,a] != [255,255,255]).all() and \
(img[b+4,a] != [255,255,255]).all() and \
(img[b+5,a] != [255,255,255]).all() and \
(img[b+6,a] != [255,255,255]).all() and \
(img[b+7,a] != [255,255,255]).all() and \
(img[b+8,a] != [255,255,255]).all() and \
(img[b+9,a] != [255,255,255]).all() and \
(img[b+10,a] != [255,255,255]).all() and \
(img[b+11,a] != [255,255,255]).all() and \
(img[b+12,a] != [255,255,255]).all() :
    b = b + 1
    d.append(b)

  else :
    b = b + 1

print('d=')
print(d)

제 코드는 이렇습니다.

좌표(a,b)에서 a=450(고정)이고 b를 0~(img_h-12)(이미지끝)까지 +1해 가면서

(a,b)좌표의 픽셀이 흰색이고 (a, b+1)~(a,b+12)까지의 픽셀이 흰색이 아닌 점의

b값(y좌표)를 d 배열에 넣는 코드입니다.

이 조건을 위와같이 12번 직접 입력하는 코드가 아니라

bthick = 12 를 사용해서 표현해야만 하는데 이틀 내내 에러만 뜨네요.

어떻게 표현해야할까요 ㅠㅠ

  • (•́ ✖ •̀)
    알 수 없는 사용자

2 답변

  • 안녕하세요. :-)

    제가 Python 전문가는 아니라 '동작하는 코드'를 중심으로 작성해보았습니다. 간단히 참고 정도만 하시길 바랍니다. (2.7.x 기준)

    import numpy as np
    import cv2 as cv
    
    img = cv.imread('dp.png')
    
    img_h = img.shape[0]
    img_w = img.shape[1]
    img_bpp = img.shape[2]
    
    print(img_h, img_w, img_bpp)
    
    blue = (255,0,0)
    white = (255,255,255)
    
    a = 450
    b = 0
    c = list()
    d = list()
    e = 0
    
    bthick = 12
    
    #--------------------------------------------------
    # 검증 함수추가: check_func
    #--------------------------------------------------
    def check_func(i):
      trd_hold = [255,255,255] # RGB 문턱 값
      if i==0: # 맨 첫번째는 서로 같아야 True
        return (img[b+i,a] == trd_hold).all()
      else: # 그 이외에는서로 달라야 True
        return (img[b+i,a] != trd_hold).all()
    
    
    for b in range(0,img_h-12):
    # map 함수는 range함수에 의해 0부터 12까지 정수를 추출해 check_func의 인수로 넘겨주어 호출합니다.
      if all( map(check_func, range(0,bthick+1)) ):
        b = b + 1
        d.append(b)
      else :
        b = b + 1
    
    print('d=')
    print(d)
    

    핵심은 map함수를 이용한 것이구요, 매우 유용한 아이이니 직접 검색해서 알아보시면 좋을 듯 합니다.

    파이썬의 간결함을 가지고 긴 코드를 짧게 줄이는 스타일을 파이써닉(Pythonic)이라 표현합니다. 물론 제 코드는 아니지만요...ㅎㅎ

    도움이 되셨기를 바랍니다.

    감사합니다.

    • (•́ ✖ •̀)
      알 수 없는 사용자
  • Y축의 픽셀들로 연산하고 싶은 것이죠?

    문제는 imread 로 읽어들이면 (Y, X) 이다보니 img[0] 이 가로 즉 x 축 픽셀값(array)들이라는 것이 질문과 같은 연산을 만드는 걸겁니다.

    그러면 전치행렬을 구해서 90도 돌리면 어떨까요?

    아래와 같이 전치행렬을 구하면 img[0] 은 Y축의 픽셀값의 array 입니다.

    array 비교도 예와 같이 하면 됩니다.

    import cv2
    
    img = cv2.imread('lines-300x209.png')
    img.shape
    Out[4]: (209, 300, 3)
    
    timg = cv2.transpose(img)
    timg.shape
    Out[5]: (300, 209, 3)
    
    timg[30][0:11]
    Out[6]: array([[  0,   0,   0],
           [  0,   0,   0],
           [  0,   0,   0],
           [  0,   0,   0],
           [  0,   0,   0],
           [  0,   0,   0],
           [  0,   0,   0],
           [  0,   0,   0],
           [  0,   0,   0],
           [  0,   0,   0],
           [103, 103, 103]], dtype=uint8)
    
    (timg[30][0:11] == (((0, 0, 0),) * 11)).all()        # array 11개 비교 마지막이 [103, 103, 103] 이므로 False 
    Out[7]: False
    
    (timg[30][0:10] == (((0, 0, 0),) * 10)).all()        # array 10개 비교 10개 모두 같으므로 True
    Out[8]: True
    
    (timg[30][0:10] == (((0, 0, 0),) * 10)).all() and (timg[30][10] == (103, 103, 103)).all()    # and 로 11번째 요소 비교 같으므로 True
    Out[9]: True
    

    아 또한 전치행렬을 구하는 대신 아래와 같이 하면 30 열을 얻을 수 있습니다.

    img[:,30]    # 30열 array 입니다.
    
    img[:,30][0:11]  # 위의 transpose 한 것과 같습니다.
    Out[15]: array([[  0,   0,   0],
           [  0,   0,   0],
           [  0,   0,   0],
           [  0,   0,   0],
           [  0,   0,   0],
           [  0,   0,   0],
           [  0,   0,   0],
           [  0,   0,   0],
           [  0,   0,   0],
           [  0,   0,   0],
           [103, 103, 103]], dtype=uint8)
    
    • 자세한 설명 정말 감사합니다! 계속 진행해가는데 위에 알려주신 개념 쓰면 훨씬 수월할것같습니다!! 알 수 없는 사용자 2018.12.1 12:51

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)