Pillow 이미지 서치(Image Search) 2
Python 2018. 12. 2. 20:05 |반응형
'Pillow 이미지 서치(Image search) 1' 은 target과 source의 모든 픽셀이 정확히 일치하는 경우만 True로 판단 하기 때문에 PNG나 BMP같은 무손실 압축 그래픽 파일에만 적용 가능하다. JPEG같은 손실 압축 그래픽 파일은 target과 source의 오차를 감안해야 한다.
2018/11/30 - [Software/Python] - Pillow 이미지 서치(Image Search) 1
2019/07/08 - [Software/OpenCV] - Template Matching(Image Searching) - 부분 이미지 검색
Target: 93 X 47
Source: 600 X 600
강아지의 앞발에 위치한 타겟 위치를 찾아 보자.
Tolerance: 30
Step: 2
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
|
from PIL import Image
from PIL import ImageDraw
from PIL import ImageChops
from PIL import ImageStat
import sys
import time
source = Image.open("source.jpg")
sx, sy = source.size
target = Image.open("target.jpg")
tx, ty = target.size
tolerance = 30 # 오차 범위는 30 정도면 적당한거 같다.
step = 2 # 모든 픽셀을 검사하면 너무 오랜 시간이 걸린다. 한 개 건너 한 개 픽셀만 검사.
print("Source size: ", source.size)
print("Target size: ", target.size)
trial = 0 # Image search 시도 횟수.
def Search(cx, cy, tolerance):
compare = source.crop((cx, cy, cx + tx, cy + ty)) # 소스에서 타겟으로 판단되는 위치의 이미지를 타겟 사이즈 만큼 잘라낸다.
# Returns a rectangular region from this image. The box is a 4-tuple defining the left, upper, right, and lower pixel coordinate.
print("Compare size: ", compare.size)
diff = ImageChops.difference(compare, target) # 타겟과 타겟으로 판단되는 부분의 픽셀값 비교.
stat = ImageStat.Stat(diff)
global trial
if max(max(stat.extrema[0]), max(stat.extrema[1]), max(stat.extrema[2])) <= tolerance:
print("Target found(Min, max): ", stat.extrema)
return True
else:
trial += 1
return False
draw = ImageDraw.Draw(source) # Creates an object that can be used to draw in the given image.
start = time.time()
for y in range(sy - ty): # 소스의 처음부터 타겟 사이즈를 뺀 위치 까지 전체 검색을 시작 한다.
for x in range(0, sx - tx, step): # 처음 (10 X 10)개 픽셀의 값이 비슷 하다면 Search()로 타겟 사이즈 전체를 다시 확인한다.
compare = source.crop((x, y, x + 10, y + 10))
partial_target = target.crop((0, 0, 10, 10))
diff = ImageChops.difference(compare, partial_target) # 각 픽셀값 차의 절대값이 반환 된다.
# Returns the absolute value of the pixel-by-pixel difference between the two images.
stat = ImageStat.Stat(diff)
if max(max(stat.extrema[0]), max(stat.extrema[1]), max(stat.extrema[2])) < tolerance:
if Search(x, y, tolerance) == True:
print("Top left point: (%d, %d)" %(x, y))
print("Center of targe point: (%d, %d)" %(x + target.width / 2, y + target.height / 2))
print("Number of total wrong detection: ", trial)
draw.rectangle((x, y, x + target.width, y + target.height), outline = (255, 0, 0))
# Draws a rectangle. 소스 이미지의 타겟 부분에 빨간 사각형을 그린다.
end = time.time()
print("Seraching time: ", end - start)
source.show()
sys.exit()
else:
print("At (%d, %d): Target not found" %(x, y))
print("Wrong detection count: ", trial)
end = time.time()
print("Image search failed.")
print("Seraching time: ", end - start)
|
소스를 입력하고 빌드한다.
123번 잘못된 지점을 검색했고 (232, 497)위치의 Target을 찾는데 총 15.66초가 걸렸다.
JPEG파일의 손실 압축 때문에 Target과 Source의 픽셀이 최대 RGB(16, 9, 15)만큼 차이가 발생 했다.
Target을 찾지 못한다면 Step과 Tolerance 값을 적당히 수정해야 한다.
반응형
'Python' 카테고리의 다른 글
sqlite3 - DB API 2.0 interface for SQLite databases (4) | 2019.01.21 |
---|---|
Pillow 차선 감지(Lane Detection) (0) | 2018.12.03 |
Pillow 이미지 서치(Image Search) 1 (0) | 2018.11.30 |
pywin32 Windows Extensions for Python 2 (0) | 2018.11.27 |
pywin32 Windows Extensions for Python 1 (0) | 2018.11.27 |