OpenCV-간단한 그래픽 및 이벤트 처리

6 minute read

참고사항
현재 Post에서 사용하는 Data를 만드는 법이나 사용한 Image는 github에 올려두었습니다.

직선 및 사각형 그리기


cv.line(img,pt1,pt2,color[, thickness[, LineType[, shift]]]): pt1에서 pt2까지 연결하는 직선 그리기
parameter

  • pt1: 시작점
  • pt2: 끝점
  • color: 색상
  • thickness: 선 두께
  • lineType: cv2.LINE_8(Default),cv2.LINE_4(),cv2.LINE_AA()
  • shift: 각 좌표에 대한 비트 이동


cv.rectangle(img,pt1,pt2,color[, thickness[, LineType[, shift]]]): pt1에서 pt2에 의해 정의되는 사각형 그리기
parameter

  • pt1: 시작점
  • pt2: 끝점
  • color: 색상
  • thickness: 선 두께
  • lineType: cv2.LINE_8(Default),cv2.LINE_4(),cv2.LINE_AA()
  • shift: 각 좌표에 대한 비트 이동


cv.clipline(imgRect,pt1,pt2): pt1에서 pt2까지의 직선이 imgRect 사각형에 의해 절단되는 좌표점을 계산하여 pt1과 pt2를 반환한다. 직선이 사각 영역 밖에 있으면 retval에 False를 반환한다.

배경및 그리기 Method 선언

앞으로 많이 사용할 matplotlib을 활용한 image그리기 및 배경 그리기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def background_img():
    img = np.zeros((512,512,3),dtype=np.int32)+255 # 512 x 512 x 3(Color)의 Backgroud 생성

    cv2.line(img,(0,0),(500,0),(0,0,0),5)
    cv2.line(img,(0,0),(0,500),(0,0,0),5)
    cv2.line(img,(500,0),(500,500),(0,0,0),5)
    cv2.line(img,(0,500),(500,500),(0,0,0),5)
    
    return img

def plot(img):
    plt.axis('off')
    plt.imshow(img)
    plt.show()


직선 및 사각형 그리기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
img = np.zeros((512,512,3),dtype=np.int32)+255 # 512 x 512 x 3(Color)의 Backgroud 생성

pt1 = 100,100
pt2 = 400,400
cv2.rectangle(img,pt1,pt2,(0,255,0),2) #img영상에 pt1(100,100), pt2(400,400)의 크기의 녹색(0,255,0), 두께2로서 그린다

cv2.line(img,(0,0),(500,0),(255,0,0),5)
cv2.line(img,(0,0),(0,500),(0,0,255),5)
cv2.line(img,(500,0),(500,500),(0,0,0),5)
cv2.line(img,(0,500),(500,500),(0,0,0),5)

plt.axis('off')
plt.imshow(img)
plt.show()


직선 및 사각형 그리기 결과


직선-사각형 교차점 그리기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
img = np.zeros((512,512,3),dtype=np.int32)+255 # 512 x 512 x 3(Color)의 Backgroud 생성

x1,x2 = 100,400
y1,y2 = 100,400
cv2.rectangle(img,(x1,y1),(x2,y2),(0,255,0),5)

pt1 = 120,5
pt2 = 300,500

cv2.line(img,pt1,pt2,(0,0,255),5)

imgRect = (x1,y1,x2-x1,y2-y1)
retval, rpt1, rpt2 = cv2.clipLine(imgRect,pt1,pt2)

if retval:
    cv2.circle(img,rpt1,radius=10,color=(255,0,0),thickness=-1)
    cv2.circle(img,rpt2,radius=10,color=(255,0,0),thickness=-1)
    
plot(img)


직선-사각형 교차점 그리기 결과



원 및 타원 그리기


cv.circle(img,center,radius,color[, thickness[, LineType[, shift]]]): 원 그리기
parameter

  • center: 중심점
  • radius: 반지름
  • color: 색상
  • thickness: 선 두께 (-1일시 안의 색상 채움)


cv.ellipse(img,center,axes,angle,startAngle,endAngle,color[, thickness[, LineType[, shift]]]): 타원 그리기
parameter

  • center: 중심점
  • axes: 주축의 크기의 절반
  • angle: 회전각도
  • startAngle: 호의 시작 각도
  • endAngle: 호의 끝 각도


cv.ellipse(img,box,color[, thickness[, LineType]]): 회전 사각형 내접 타원
parameter

  • box: (center,size,angle) 회전 사각형


cv.ellipse2Poly(center,axes,angle,arcStart,arcEnd,delta): 타원 위 좌표 계산
parameter

  • center: 중심점
  • axes: 주축의 크기의 절반
  • angle: 회전각도
  • arcStart: 호의 시작 각도
  • arcEnd: 호의 끝 각도
  • delta: 각도 간격


원 그리기

1
2
3
4
5
6
7
8
9
10
11
img = background_img()

cx = img.shape[0]//2
cy = img.shape[1]//2

for r in range(200,0,-100):
    cv2.circle(img,(cx,cy),r,color=(255,0,0), thickness=2)
    
cv2.circle(img,(cx,cy),radius=50,color=(0,0,255),thickness=-1)

plot(img)


원 그리기


타원 그리기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
img = background_img()

ptCenter = img.shape[0]//2, img.shape[1]//2
size = 200,50

# 중심, 축 절반 크기(가로, 세로), 각도, 시작각도, 끝각도, 색상, 선 두께
cv2.ellipse(img,ptCenter,size,0,0,360,(255,0,0),10)
cv2.ellipse(img,ptCenter,size,45,0,360,(0,0,255),3)

box = (ptCenter,size,0)
cv2.ellipse(img,box,(255,0,0),0,4)

box = (ptCenter,size,45)
cv2.ellipse(img,box,(0,0,255),5,6)

plot(img)


타원 그리기 결과



다각형 그리기


cv.polylines(img,pts,isClosed,color[, thickness[, LineType[, shift]]]): 다각형 그리기
parameter

  • pts: 좌표(다각형들의 numpy 배열)
  • isClosed: if True=> 닫힌 사각형


cv.fillConvexPoly(img,points,color[, thickness[, LineType[, shift]]]): 볼록 다각형 채우기
parameter

  • points: 좌표(다각형들의 numpy 배열)
  • color: 다각형을 채울 색깔


cv.fillPoly(img,pts,color[, thickness[, LineType[, offset]]]): 다각형 채우기
parameter

  • pts: 좌표(다각형들의 numpy 배열)


다각형 그리기

1
2
3
4
5
6
7
8
img = background_img()

pts1 = np.array([[100,100],[200,100],[200,200],[100,300],[100,200]])
pts2 = np.array([[300,200],[400,100],[400,200]])

cv2.polylines(img,[pts1,pts2], isClosed = True, color = (255,0,0),thickness=5)

plot(img)


다각형 그리기 결과


다각형 그리기2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
img = background_img()

ptCenter = img.shape[0]//2, img.shape[1]//2
size = 200,100

cv2.ellipse(img,ptCenter,size,0,0,360,(255,0,0),3)
pts1 = cv2.ellipse2Poly(ptCenter,size,0,0,360,delta=45)

cv2.ellipse(img,ptCenter,size,45,0,360,(255,0,0),3)
pts2 = cv2.ellipse2Poly(ptCenter,size,45,0,360,delta=45)

cv2.polylines(img,[pts1,pts2], isClosed=True, color=(0,0,255), thickness=3)

plot(img)


다각형 그리기2 결과


회전 사각형

1
2
3
4
5
6
7
8
9
10
11
12
13
14
img = background_img()

x,y = 256,256
size = 200

for angle in range(0,90,10):
    rect = ((256,256),(size,size),angle)
    box = cv2.boxPoints(rect).astype(np.int32)
    r=np.random.randint(256)
    g=np.random.randint(256)
    b=np.random.randint(256)
    cv2.polylines(img,[box],True,(r,g,b),2)

plot(img)


회전 사각형 결과


다각형 채우기

1
2
3
4
5
6
7
8
img = background_img()

pts1 = np.array([[100,100],[200,100],[200,200],[100,300],[100,200]])
pts2 = np.array([[300,200],[400,100],[400,200]])

cv2.fillPoly(img,[pts1,pts2], color = (255,0,0))

plot(img)


다각형 채우기 결과



문자열 출력


cv.getTextSize(text,fontFace,fontScale,thickness): 문자열 출력 크기 변환
parameter

  • text: 출력할 문자
  • fontFace: 문자 Style, ex)cv2.FONT_HERSHEY_PLAIN
  • fontScale: 문자 크기
  • thickness: 문자 두께


cv.putText(img,text,org,fontFace,fontScale,color[, thickness[, LineType[, bottonLeftOrigin]]]): 타원 그리기
parameter

  • org: 사각형 왼쪽 아래 좌표 위치


문자열 출력

1
2
3
4
5
6
7
8
9
10
11
12
img = background_img()

text = 'OpenCV Programming'
org = (30,100)
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img,text,org,font,1.3,(255,0,0),2)

size,baseLine = cv2.getTextSize(text,font,1.3,10)
cv2.rectangle(img,org,(org[0]+size[0],org[1]-size[1]),(0,0,255),2)
cv2.circle(img,org,3,(0,255,0),2)

plot(img)


문자열 출력 결과



마우스 이벤트 처리

이전 Post OpenCV-영상 및 비디오 입출력에서 사전사항으로 적어두었던 ipywidgets를 활용하여 OpenCV같은 기능을 넣었다.

Widgets은 Java에서의 Swing과 같은 개념으로서 작동한다.
기본적으로 2가지의 구성요소로 widgets이 생성된다고 생각한다.

Component: Widgets을 구성하는 구성요소 이다.

  • box: 전체 Component를 포함할 하나의 Component (Box)
  • button1: Up Button Component (Button)
  • button2: Down Button Component (Button)
  • button3: Left Button Component (Button)
  • button4: Right Button Component (Button)
  • wImg: 출력 결과를 보여줄 Component (Image)

Event: 각각의 Component에 대한 Event를 정의할 수 있다.

  • up_button_clicked: button1 Component Click시 y축 위로 이동
  • down_button_clicked: button2 Component Click시 y축 아래로 이동
  • left_button_clicked: button3 Component Click시 x축 왼쪽으로 이동
  • right_button_clicked: button4 Component Click시 x축 오른쪽으로 이동


참고 사이트
Component 설명: 정식 사이트
Event 설명: 정식 사이트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
button1 = Button(description="Up")
button2 = Button(description="Down")
button3 = Button(description="Left")
button4 = Button(description="Right")

wImg = Image(layout = Layout(border="solid"), width="50%") 

box_layout = Layout(display='flex',
                    flex_flow='row',
                    border='solid',
                   width='100%',)

items = [button1,button2,button3,button4]

box = Box(children=items)

display.display(box, wImg)

width, height = 512,512
x,y,R = 256,256,50

def up_button_clicked(b):
    global y,R
    
    if y - 10 > R:
        y = y-10
    else:
        y = R
    draw_some()
    
def down_button_clicked(b):
    global y,R,height
    
    if y + R < height:
        y += 10
    else:
        y = height - R
    draw_some()

def left_button_clicked(b):
    global x,R
    if x - 10 > R:
        x -= 10
    else:
        x = R
    draw_some()
    
def right_button_clicked(b):
    global x,R,width
    
    if x + R < width:
        x += 10
    else:
        x = width - R
    draw_some()
    
def draw_some():
    global x,y,R
    img = np.zeros((512,512,3),dtype=np.int32)+255
    cv2.circle(img,(x,y),R,(0,0,255),-1)
        
    tmpStream = cv2.imencode(".jpeg", img)[1].tostring()
    wImg.value = tmpStream
    
draw_some()


button1.on_click(up_button_clicked)
button2.on_click(down_button_clicked)
button3.on_click(left_button_clicked)
button4.on_click(right_button_clicked)


마우스 이벤트 처리 결과



트랙바 이벤트 처리


Component: Widgets을 구성하는 구성요소 이다.

  • box: 전체 Component를 포함할 하나의 Component (Box)
  • IntSlider_Red: Image R 값 정의 Component (IntSlider=트랙바)
  • IntSlider_Green: Image G 값 정의 Component (IntSlider=트랙바)
  • IntSlider_Blue: Image B 값 정의 Component (IntSlider=트랙바)
  • wImg: 출력 결과를 보여줄 Component (Image)

Event: 각각의 Component에 대한 Event를 정의할 수 있다.

  • on_value_change_red: Image RGB값 중 R값 정의
  • on_value_change_green: Image RGB값 중 G값 정의
  • on_value_change_blue: Image RGB값 중 B값 정의


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
IntSlider_Red = IntSlider(
    value=0,
    min=0,
    max=255,
    step=1,
    description='Red: ',
    disabled=False,
    continuous_update=False,
    orientation='horizontal',
    readout=True,
    readout_format='d'
)

IntSlider_Green = IntSlider(
    value=0,
    min=0,
    max=255,
    step=1,
    description='Green: ',
    disabled=False,
    continuous_update=False,
    orientation='horizontal',
    readout=True,
    readout_format='d'
)

IntSlider_Blue = IntSlider(
    value=0,
    min=0,
    max=255,
    step=1,
    description='Blue: ',
    disabled=False,
    continuous_update=False,
    orientation='horizontal',
    readout=True,
    readout_format='d'
)

wImg = Image(layout = Layout(border="solid"), width="50%") 

box_layout = Layout(display='flex',
                    flex_flow='row',
                    border='solid',
                   width='100%',)

items = [IntSlider_Red,IntSlider_Green,IntSlider_Blue]

box = Box(children=items)

display.display(box, wImg)

def draw_some():
    global b,g,r
    img = np.zeros((512,512,3),dtype=np.int)
    img[:] = (b,g,r)
    tmpStream = cv2.imencode(".jpeg", img)[1].tostring()
    wImg.value = tmpStream

    
b,g,r = 0,0,0
draw_some()

def on_value_change_red(change):
    global r
    r = change['new']
    draw_some()
    
def on_value_change_blue(change):
    global g
    g = change['new']
    draw_some()
    
def on_value_change_green(change):
    global b
    b = change['new']
    draw_some()

IntSlider_Red.observe(on_value_change_red, names='value')
IntSlider_Green.observe(on_value_change_blue, names='value')
IntSlider_Blue.observe(on_value_change_green, names='value')


트랙바 이벤트 처리 결과


참조:원본코드
참조:Python으로 배우는 OpenCV 프로그래밍
문제가 있거나 궁금한 점이 있으면 wjddyd66@naver.com으로 Mail을 남겨주세요.

Categories:

Updated:

Leave a comment