Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
O
Open_CV
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
parkminwoo
Open_CV
Commits
32b8c0bd
Commit
32b8c0bd
authored
4 years ago
by
parkminwoo
Browse files
Options
Downloads
Patches
Plain Diff
delete unnecessary
parent
7efe4098
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
Untitled.ipynb
+0
-6
0 additions, 6 deletions
Untitled.ipynb
comment.ipynb
+0
-225
0 additions, 225 deletions
comment.ipynb
with
0 additions
and
231 deletions
Untitled.ipynb
deleted
100644 → 0
+
0
−
6
View file @
7efe4098
{
"cells": [],
"metadata": {},
"nbformat": 4,
"nbformat_minor": 4
}
This diff is collapsed.
Click to expand it.
comment.ipynb
deleted
100644 → 0
+
0
−
225
View file @
7efe4098
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "solved-logan",
"metadata": {},
"outputs": [],
"source": [
"# 가장 큰 영역을 갖는 컨투어를 찾는다.\n",
"# param : contours - 컨투어들의 리스트이다.\n",
"# return : max_index - contours에서 가장 큰 영역을 갖는 컨투어의 인덱스이다.\n",
"def findMaxArea(contours):\n",
" max_area = -1\n",
" max_index = -1\n",
" \n",
" # 가장 큰 영역을 갖는 컨투어를 찾는다.\n",
" for i,contour in enumerate(contours):\n",
" # cv2.contourArea : 컨투어의 넓이를 얻는다.\n",
" area = cv2.contourArea(contour) \n",
" # cv.boundingRect : 컨투어 라인을 둘러싸는 사각형을 그린다.\n",
" x,y,w,h = cv2.boundingRect(contour)\n",
" if (w*h)*0.4 > area:\n",
" continue\n",
" if w > h:\n",
" continue\n",
" if area > max_area:\n",
" max_area = area\n",
" max_index = i \n",
" if max_area < 10000:\n",
" max_index = -1\n",
" \n",
" return max_index"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "parental-police",
"metadata": {},
"outputs": [],
"source": [
"# 이미지(문서 영역)를 정면 방향으로 변환한다.\n",
"# param : img_input - 정면 방향으로 변환할 이미지이다, points - img_input의 꼭짓점이다.\n",
"# return : img_warped - 정면 방향으로 변환된 이미지이다.\n",
"def transform(img_input, points):\n",
" # sort_points(): 다음 순서를 갖도록 꼭지점을 정렬한다.\n",
" # top left, top right, bottom right, bottom left\n",
" points = sort_points(points)\n",
" topLeft, topRight, bottomRight, bottomLeft = points\n",
" print(topLeft, topRight, bottomRight, bottomLeft)\n",
" print(topLeft[0] + topLeft[1], topRight[0]+topRight[1],\n",
" bottomRight[0]+bottomRight[1], bottomLeft[0]+bottomLeft[1])\n",
" \n",
" # 변환 후, 이미지(문서 영역)의 너비와 높이를 결정한다.\n",
" topWidth = distance(bottomLeft, bottomRight)\n",
" bottomWidth = distance(topLeft, topRight)\n",
" maxWidth = max(int(topWidth), int(bottomWidth))\n",
" leftHeight = distance(topLeft, bottomLeft)\n",
" rightHeight = distance(topRight, bottomRight)\n",
" maxHeight = max(int(leftHeight), int(rightHeight))\n",
" \n",
" # 정면 방향의 이미지(문서 영역)의 좌표를 결정한다.\n",
" dst = np.array([[0, 0],[maxWidth - 1, 0],\n",
" [maxWidth - 1, maxHeight - 1],[0, maxHeight - 1]], \n",
" dtype = \"float32\")\n",
" \n",
" # 정면 방향의 이미지(문서 영역)로 변환한다.\n",
" H = cv2.getPerspectiveTransform(points, dst)\n",
" img_warped = cv2.warpPerspective(img_input, H, (maxWidth, maxHeight))\n",
" \n",
" return img_warped"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "stupid-playback",
"metadata": {},
"outputs": [],
"source": [
"# 다음 순서를 갖도록 꼭짓점을 정렬한다.\n",
"# top left, top right, bottom right, bottom left\n",
"# param : points - 정렬되기 전의 꼭짓점의 ndarray이다.\n",
"# return : new_points - 정렬된 후의 꼭짓점의 ndarray이다.\n",
"def sort_points(points):\n",
" points = points.astype(np.float32)\n",
" new_points = np.zeros((4, 2), dtype = \"float32\")\n",
" \n",
" # top left를 구한다.\n",
" s = points.sum(axis = 1)\n",
" min_index = np.argmin(s)\n",
" new_points[0] = points[min_index]\n",
" points = np.delete(points, min_index, axis = 0)\n",
" \n",
" # bottom right를 구한다.\n",
" s = points.sum(axis = 1)\n",
" max_index = np.argmax(s)\n",
" new_points[2] = points[max_index]\n",
" points = np.delete(points, max_index, axis = 0)\n",
"\n",
" # top right, bottom left를 구한다.\n",
" v0 = points[0] - new_points[0]\n",
" v1 = points[1] - new_points[0]\n",
" \n",
" # angle_between() : 벡터 사이의 각도를 구한다.\n",
" angle = angle_between(v0, v1)\n",
" if angle < 0:\n",
" new_points[1] = points[1]\n",
" new_points[3] = points[0]\n",
" else:\n",
" new_points[1] = points[0]\n",
" new_points[3] = points[1]\n",
" \n",
" return new_points"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "antique-acrobat",
"metadata": {},
"outputs": [],
"source": [
"# 두 벡터 사이의 각도를 구한다.\n",
"# param : A, B - 벡터를 표현한 ndarray이다.\n",
"# return : angle - 벡터 A와 B 사이의 각도이다.\n",
"def angle_between(A, B):\n",
" x1 = A[0]\n",
" y1 = A[1]\n",
" x2 = B[0]\n",
" y2 = B[1]\n",
"\n",
" dot = x1*x2 + y1*y2 \n",
" det = x1*y2 - y1*x2\n",
" angle = np.arctan2(det, dot) * 180/np.pi \n",
"\n",
" return angle"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ambient-canberra",
"metadata": {},
"outputs": [],
"source": [
"# 사용자의 마우스 입력을 통하여 이미지(문서 영역)의 꼭지점을 조정하는 마우스 콜백 함수이다.\n",
"# param : event - 마우스 이벤트이다, (x, y) - 윈도우 창을 기준으로 좌측 상단점 좌표이다, \n",
"# flags - 마우스 이벤트가 발생할 때 키보드 또는 마우스 상태이다,\n",
"# param - 전달하고 싶은 데이터로 사용하지 않아도 매개변수로 받아야 한다.\n",
"# return : none\n",
"def mouse_callback(event, x ,y, flags, param):\n",
" global mouse_is_pressing, points\n",
" \n",
" # step == 1 이면,마우스 콜백 함수가 등록된 것이다.\n",
" # step != 1 이면, cv2.setMouseCallback()을 통해 마우스 콜백 함수가 등록되지 않은 것이다.\n",
" if step != 1:\n",
" return\n",
"\n",
" # CASE 1 - 마우스가 움직이고\n",
" if event == cv2.EVENT_MOUSEMOVE: \n",
" # 눌린 상태일 때,\n",
" if mouse_is_pressing == True: \n",
" # 마우스의 좌표와, 포인트(꼭짓점)의 거리가 가깝다면, 꼭지점을 이동한다.\n",
" for i,point in enumerate(points):\n",
" if distance((x,y), point) < 15: \n",
" points[i][0] = x \n",
" points[i][1] = y\n",
" break\n",
" \n",
" # CASE 2 - 마우스 왼쪽 버튼이 눌린 상태일 때, ` \n",
" elif event == cv2.EVENT_LBUTTONDOWN: \n",
" # 꼭짓점과의 거리가 가깝다면 mouse_is_pressing을 True로 바꾼다.\n",
" for point in points:\n",
" if distance((x,y), point) < 10:\n",
" mouse_is_pressing = True\n",
" break\n",
" \n",
" # CASE3 - 마우스 왼쪽 버튼이 눌려있지 않으면, mouse_is_pressing을 False로 바꿈\n",
" elif event == cv2.EVENT_LBUTTONUP: \n",
" mouse_is_pressing = False"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "circular-clear",
"metadata": {},
"outputs": [],
"source": [
"# 두 점 사이의 거리를 구한다.\n",
"# param : point1, point2 - 거리를 구할 두 점이다.\n",
"# return : point1, point2 사이의 거리이다.\n",
"def distance(point1, point2):\n",
" \n",
" x1, y1 = point1\n",
" x2, y2 = point2\n",
" \n",
" return int(np.sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2)))"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.1"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
%% Cell type:code id:solved-logan tags:
```
python
# 가장 큰 영역을 갖는 컨투어를 찾는다.
# param : contours - 컨투어들의 리스트이다.
# return : max_index - contours에서 가장 큰 영역을 갖는 컨투어의 인덱스이다.
def
findMaxArea
(
contours
):
max_area
=
-
1
max_index
=
-
1
# 가장 큰 영역을 갖는 컨투어를 찾는다.
for
i
,
contour
in
enumerate
(
contours
):
# cv2.contourArea : 컨투어의 넓이를 얻는다.
area
=
cv2
.
contourArea
(
contour
)
# cv.boundingRect : 컨투어 라인을 둘러싸는 사각형을 그린다.
x
,
y
,
w
,
h
=
cv2
.
boundingRect
(
contour
)
if
(
w
*
h
)
*
0.4
>
area
:
continue
if
w
>
h
:
continue
if
area
>
max_area
:
max_area
=
area
max_index
=
i
if
max_area
<
10000
:
max_index
=
-
1
return
max_index
```
%% Cell type:code id:parental-police tags:
```
python
# 이미지(문서 영역)를 정면 방향으로 변환한다.
# param : img_input - 정면 방향으로 변환할 이미지이다, points - img_input의 꼭짓점이다.
# return : img_warped - 정면 방향으로 변환된 이미지이다.
def
transform
(
img_input
,
points
):
# sort_points(): 다음 순서를 갖도록 꼭지점을 정렬한다.
# top left, top right, bottom right, bottom left
points
=
sort_points
(
points
)
topLeft
,
topRight
,
bottomRight
,
bottomLeft
=
points
print
(
topLeft
,
topRight
,
bottomRight
,
bottomLeft
)
print
(
topLeft
[
0
]
+
topLeft
[
1
],
topRight
[
0
]
+
topRight
[
1
],
bottomRight
[
0
]
+
bottomRight
[
1
],
bottomLeft
[
0
]
+
bottomLeft
[
1
])
# 변환 후, 이미지(문서 영역)의 너비와 높이를 결정한다.
topWidth
=
distance
(
bottomLeft
,
bottomRight
)
bottomWidth
=
distance
(
topLeft
,
topRight
)
maxWidth
=
max
(
int
(
topWidth
),
int
(
bottomWidth
))
leftHeight
=
distance
(
topLeft
,
bottomLeft
)
rightHeight
=
distance
(
topRight
,
bottomRight
)
maxHeight
=
max
(
int
(
leftHeight
),
int
(
rightHeight
))
# 정면 방향의 이미지(문서 영역)의 좌표를 결정한다.
dst
=
np
.
array
([[
0
,
0
],[
maxWidth
-
1
,
0
],
[
maxWidth
-
1
,
maxHeight
-
1
],[
0
,
maxHeight
-
1
]],
dtype
=
"
float32
"
)
# 정면 방향의 이미지(문서 영역)로 변환한다.
H
=
cv2
.
getPerspectiveTransform
(
points
,
dst
)
img_warped
=
cv2
.
warpPerspective
(
img_input
,
H
,
(
maxWidth
,
maxHeight
))
return
img_warped
```
%% Cell type:code id:stupid-playback tags:
```
python
# 다음 순서를 갖도록 꼭짓점을 정렬한다.
# top left, top right, bottom right, bottom left
# param : points - 정렬되기 전의 꼭짓점의 ndarray이다.
# return : new_points - 정렬된 후의 꼭짓점의 ndarray이다.
def
sort_points
(
points
):
points
=
points
.
astype
(
np
.
float32
)
new_points
=
np
.
zeros
((
4
,
2
),
dtype
=
"
float32
"
)
# top left를 구한다.
s
=
points
.
sum
(
axis
=
1
)
min_index
=
np
.
argmin
(
s
)
new_points
[
0
]
=
points
[
min_index
]
points
=
np
.
delete
(
points
,
min_index
,
axis
=
0
)
# bottom right를 구한다.
s
=
points
.
sum
(
axis
=
1
)
max_index
=
np
.
argmax
(
s
)
new_points
[
2
]
=
points
[
max_index
]
points
=
np
.
delete
(
points
,
max_index
,
axis
=
0
)
# top right, bottom left를 구한다.
v0
=
points
[
0
]
-
new_points
[
0
]
v1
=
points
[
1
]
-
new_points
[
0
]
# angle_between() : 벡터 사이의 각도를 구한다.
angle
=
angle_between
(
v0
,
v1
)
if
angle
<
0
:
new_points
[
1
]
=
points
[
1
]
new_points
[
3
]
=
points
[
0
]
else
:
new_points
[
1
]
=
points
[
0
]
new_points
[
3
]
=
points
[
1
]
return
new_points
```
%% Cell type:code id:antique-acrobat tags:
```
python
# 두 벡터 사이의 각도를 구한다.
# param : A, B - 벡터를 표현한 ndarray이다.
# return : angle - 벡터 A와 B 사이의 각도이다.
def
angle_between
(
A
,
B
):
x1
=
A
[
0
]
y1
=
A
[
1
]
x2
=
B
[
0
]
y2
=
B
[
1
]
dot
=
x1
*
x2
+
y1
*
y2
det
=
x1
*
y2
-
y1
*
x2
angle
=
np
.
arctan2
(
det
,
dot
)
*
180
/
np
.
pi
return
angle
```
%% Cell type:code id:ambient-canberra tags:
```
python
# 사용자의 마우스 입력을 통하여 이미지(문서 영역)의 꼭지점을 조정하는 마우스 콜백 함수이다.
# param : event - 마우스 이벤트이다, (x, y) - 윈도우 창을 기준으로 좌측 상단점 좌표이다,
# flags - 마우스 이벤트가 발생할 때 키보드 또는 마우스 상태이다,
# param - 전달하고 싶은 데이터로 사용하지 않아도 매개변수로 받아야 한다.
# return : none
def
mouse_callback
(
event
,
x
,
y
,
flags
,
param
):
global
mouse_is_pressing
,
points
# step == 1 이면,마우스 콜백 함수가 등록된 것이다.
# step != 1 이면, cv2.setMouseCallback()을 통해 마우스 콜백 함수가 등록되지 않은 것이다.
if
step
!=
1
:
return
# CASE 1 - 마우스가 움직이고
if
event
==
cv2
.
EVENT_MOUSEMOVE
:
# 눌린 상태일 때,
if
mouse_is_pressing
==
True
:
# 마우스의 좌표와, 포인트(꼭짓점)의 거리가 가깝다면, 꼭지점을 이동한다.
for
i
,
point
in
enumerate
(
points
):
if
distance
((
x
,
y
),
point
)
<
15
:
points
[
i
][
0
]
=
x
points
[
i
][
1
]
=
y
break
# CASE 2 - 마우스 왼쪽 버튼이 눌린 상태일 때, `
elif
event
==
cv2
.
EVENT_LBUTTONDOWN
:
# 꼭짓점과의 거리가 가깝다면 mouse_is_pressing을 True로 바꾼다.
for
point
in
points
:
if
distance
((
x
,
y
),
point
)
<
10
:
mouse_is_pressing
=
True
break
# CASE3 - 마우스 왼쪽 버튼이 눌려있지 않으면, mouse_is_pressing을 False로 바꿈
elif
event
==
cv2
.
EVENT_LBUTTONUP
:
mouse_is_pressing
=
False
```
%% Cell type:code id:circular-clear tags:
```
python
# 두 점 사이의 거리를 구한다.
# param : point1, point2 - 거리를 구할 두 점이다.
# return : point1, point2 사이의 거리이다.
def
distance
(
point1
,
point2
):
x1
,
y1
=
point1
x2
,
y2
=
point2
return
int
(
np
.
sqrt
(
pow
(
x1
-
x2
,
2
)
+
pow
(
y1
-
y2
,
2
)))
```
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment