파이썬 긴 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)
댓글 입력