반응형

아래와 같은 도로 이미지에서 차선 부분만 감지 한다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from PIL import Image
from PIL import ImageFilter
 
source = Image.open("road.jpg")
result = Image.new("RGB", source.size)
# Creates a new image with the given mode and size.
sx, sy = source.size
horizon = 550 # 550픽셀 아래에 도로가 있다고 가정.
 
for y in range(horizon, sy):
    for x in range(sx):
        if min(source.getpixel((x, y))) > 0xf0:
            result.putpixel((x, y), (0xff0xff0xff))
            # RGB값 중 최소값이 0xf0이상이면 흰색으로 변경
 
result = result.filter(ImageFilter.FIND_EDGES)
#result = result.filter(ImageFilter.BoxBlur(1))
# Filters this image using the given filter.
result.save("result.jpg")
# Saves this image under the given filename.
result.show()
cs


결과:

반응형
Posted by J-sean
:
반응형

'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) - 부분 이미지 검색

2019/07/10 - [Software/OpenCV] - Template Matching(Image Searching) for multiple objects - 반복되는 이미지 모두 찾기

2019/07/12 - [Software/OpenCV] - Template Matching(Image Searching) with a mask for multiple objects - 마스크를 이용해 (배경이 다른) 반복되는 이미지 모두 찾기

 

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((001010))
        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 = (25500))
                # 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 값을 적당히 수정해야 한다.

 

반응형
Posted by J-sean
:
반응형

Pillow 모듈을 사용해 큰 이미지에서 작은 부분을 찾을 수 있다. 예를 들어 아래 Target과 같이 작은 부분을 큰 Source에서 찾아야 하는 경우이다.


2018/12/02 - [Software/Python] - Pillow 이미지 서치(Image Search) 2

2019/07/08 - [Software/OpenCV] - Template Matching(Image Searching) - 부분 이미지 검색

2019/07/10 - [Software/OpenCV] - Template Matching(Image Searching) for multiple objects - 반복되는 이미지 모두 찾기

2019/07/12 - [Software/OpenCV] - Template Matching(Image Searching) with a mask for multiple objects - 마스크를 이용해 (배경이 다른) 반복되는 이미지 모두 찾기


Target:


Source:


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
from PIL import Image
from PIL import ImageDraw
from PIL import ImageChops
from PIL import ImageStat
import sys
 
source = Image.open("source.bmp")
sx, sy = source.size
target = Image.open("target.bmp")
tx, ty = target.size
 
print("Source size: ", source.size)
print("Target size: ", target.size)
 
trial = 0 # Image search 시도 횟수.
 
def Search(cx, cy):
    #for y in range(ty):
    #    for x in range(tx):
    #        if target.getpixel((x, y)) == source.getpixel((cx + x, cy + y)):
    #            continue
    #        else:
    #            return False
    #return True
 
    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 stat.sum == [000]:
        print("Target found(checksum): ", stat.sum)
        return True
    else:
        trial += 1
        return False
 
draw = ImageDraw.Draw(source)    # Creates an object that can be used to draw in the given image.
 
for y in range(sy - ty):        # 소스의 처음부터 타겟 사이즈를 뺀 위치 까지 검색을 시작 한다.
    for x in range(sx - tx):    # 처음 (2 X 2)개 픽셀의 값이 같다면 Search()로 타겟 사이즈 전체를 다시 확인한다.
        if source.getpixel((x, y)) == target.getpixel((00)) and source.getpixel((x + 1, y)) == target.getpixel((10)) \
            and source.getpixel((x, y + 1)) == target.getpixel((01)) and source.getpixel((x + 1, y + 1)) == target.getpixel((11)):
            if Search(x, y) == 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 = (25500))
                # Draws a rectangle. 소스 이미지의 타겟 부분에 빨간 사각형을 그린다.
                source.show()
                sys.exit()
            else:
                print("At (%d, %d): Target not found" %(x, y))
                print("Wrong detection count: ", trial)
 
print("Image search failed.")
cs




결과: 리트리버의 앞발 쪽에서 Target을 찾았다.

반응형
Posted by J-sean
:
반응형

Python에서 windows API를 사용 할 수 있게 해 주는 모듈이다.

간단한 Desktop GUI 예제:

 

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
import win32api
import win32gui
import win32con
import win32ui
 
#hinstance = win32api.GetModuleHandle(None)
 
hWnd = win32gui.GetDesktopWindow()
# Retrieves a handle to the desktop window. The desktop window covers the entire screen.
# The desktop window is the area on top of which other windows are painted.
hdc = win32gui.GetDC(hWnd)
#win32gui.GetDC(None)
# A handle to the window whose DC is to be retrieved. If this value is NULL, GetDC
# retrieves the DC for the entire screen.
 
hMemDC = win32gui.CreateCompatibleDC(hdc)
 
hImage = win32gui.LoadImage(None, "cat.bmp", win32con.IMAGE_BITMAP, 00, win32con.LR_LOADFROMFILE | win32con.LR_CREATEDIBSECTION);
# Loads an icon, cursor, animated cursor, or bitmap
 
hOldBitmap = win32gui.SelectObject(hMemDC, hImage)
win32gui.BitBlt(hdc, 505050 + 40050 + 272, hMemDC, 00, win32con.SRCCOPY) # Image(400, 272) at (50, 50)
# The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle of pixels
# from the specified source device context into a destination device context.
 
win32gui.SelectObject(hMemDC, hOldBitmap)
win32gui.DeleteObject(hImage)
win32gui.DeleteDC(hMemDC)
win32gui.ReleaseDC(hWnd, hdc)
cs

 

결과

 

 

실행 방식에 따라 제대로 표시가 안되는 경우가 있다.

 

1) 스크립트파일 - 우클릭 - 연결 프로그램 - Python - 표시가 안되는 경우가 있다.

2) Console - 스크립트 파일 실행 - 잘 표시 된다.

 

반응형
Posted by J-sean
:
반응형

Python에서 windows API를 사용 할 수 있게 해 주는 모듈이다.


간단한 Desktop GUI 예제:

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
import win32api
import win32gui
import win32con
import win32ui
 
hWnd = win32gui.GetDesktopWindow()
# Retrieves a handle to the desktop window. The desktop window covers the entire screen.
# The desktop window is the area on top of which other windows are painted.
hdc = win32gui.GetDC(hWnd)
#win32gui.GetDC(None)
# A handle to the window whose DC is to be retrieved. If this value is NULL, GetDC
# retrieves the DC for the entire screen.
 
red = win32api.RGB(25500)
win32gui.SetPixel(hdc, 00, red)  # (0, 0)에 빨간 점 그리기
 
MyPen = win32gui.CreatePen(win32con.PS_SOLID, 5, win32api.RGB(0,0,255));
OldPen = win32gui.SelectObject(hdc, MyPen);
 
win32gui.Rectangle(hdc, 5050100100# (50, 50, 100, 100)에 파란 선으로 사각형 그리기
 
win32gui.SelectObject(hdc, OldPen);
win32gui.DeleteObject(MyPen);
 
# 폰트 만들기
font_spec = {'name':'Arial''height':42'weight':30}
font = win32ui.CreateFont(font_spec)
#lf = win32gui.LOGFONT()
#lf.lfFaceName = "Times New Roman"
#lf.lfHeight = 100
#lf.lfWeight = win32con.FW_NORMAL
#hf = win32gui.CreateFontIndirect(lf)
 
oldfont = win32gui.SelectObject(hdc, font.GetSafeHandle())
 
win32gui.SetTextColor(hdc, win32api.RGB(255,0,0))
win32gui.SetBkColor(hdc, win32api.RGB(255,255,0))
#win32gui.SetBkMode(hdc, win32con.TRANSPARENT)
# Desktop window DC로는 SetBKMode()가 잘 작동하지 않는다
 
text = 'Software Engineer'
rect = win32gui.GetClientRect(hWnd)
win32gui.DrawText(hdc, text, len(text), rect, win32con.DT_CENTER | win32con.DT_VCENTER
                  | win32con.DT_SINGLELINE | win32con.DT_WORDBREAK)
# 화면 가운데 문자열 출력
 
win32gui.SelectObject(hdc,oldfont)
win32gui.DeleteObject(font.GetSafeHandle())
 
win32gui.ReleaseDC(hWnd, hdc)
cs


반응형

'Python' 카테고리의 다른 글

Pillow 이미지 서치(Image Search) 1  (0) 2018.11.30
pywin32 Windows Extensions for Python 2  (0) 2018.11.27
Pillow 화면 변화 감지(Pixel Checksum) 2  (0) 2018.11.21
Pillow 화면 변화 감지(Pixel Checksum) 1  (0) 2018.11.20
PyMySQL  (2) 2018.11.19
Posted by J-sean
:
반응형

'Pillow 화면 변화 감지(Pixel Checksum) 1'에서는 모든 픽셀의 값을 확인해서 좌표까지 알아내기 때문에 시간이 오래 걸린다.

ImageStat 모듈을 사용해 모든 픽셀을 확인하지 않고 전체적인 변화 여부만 감지하면 빠르게 확인 할 수 있다.


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
from PIL import Image
from PIL import ImageGrab
from PIL import ImageChops
from PIL import ImageStat
import time
 
def PixelCheck(x1, y1, x2, y2):
    im1 = ImageGrab.grab((x1, y1, x2, y2))
    # Take a snapshot of the screen. The pixels inside the bounding box are returned as an “RGB” image
    # on Windows or “RGBA” on macOS. If the bounding box is omitted, the entire screen is copied.
    while 1:
        time.sleep(0.1)
        im2 = ImageGrab.grab((x1, y1, x2, y2))
        im = ImageChops.difference(im1, im2)
        # Returns the absolute value of the pixel-by-pixel difference between the two images.
        # 마우스로 인한 변경은 반영 되지 않는다. 같은 이미지이면 difference()의 결과 이미지는 모든 픽셀이 0.
        stat = ImageStat.Stat(im)
        # Calculate statistics for the given image. If a mask is included, only the regions covered by
        # that mask are included in the statistics. You can also pass in a previously calculated histogram.
        if stat.sum != [000]: # Sum of all pixels for each band in the image.
            print("Change detected: sum[%s]: %s" %(im.getbands().__str__(), stat.sum.__str__()))
            # Returns a tuple containing the name of each band in this image. For example, getbands on
            # an RGB image returns (“R”, “G”, “B”).
            return
 
x1, y1, x2, y2 = map(int, input("Enter x1, y1, x2, y2 values: ").split()) # 추적할 영역의 좌상단, 우하단 좌표
PixelCheck(x1, y1, x2, y2)
# x1, y1, x2, y2 = input("Enter x1, y1, x2, y2 values: ").split()
# x1 = int(x1)
# y1 = int(y1)
# x2 = int(x2)
# y2 = int(y2)
cs


반응형

'Python' 카테고리의 다른 글

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
Pillow 화면 변화 감지(Pixel Checksum) 1  (0) 2018.11.20
PyMySQL  (2) 2018.11.19
Posted by J-sean
:
반응형

Pillow 라이브러리를 사용해서 바탕화면의 변화를 추적할 영역을 지정하고 영역에 변화가 있을때 변화된 영역의 좌상단 좌표를 반환 한다.

지정된 영역의 모든 pixel을 확인하기 때문에 넓은 영역을 지정할 수록 시간이 오래 걸린다.


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
from PIL import Image
from PIL import ImageGrab
from PIL import ImageChops
import time
 
def PixelCheck(x1, y1, x2, y2):
    im1 = ImageGrab.grab((x1, y1, x2, y2))
    # Take a snapshot of the screen. The pixels inside the bounding box are returned as an “RGB” image
    # on Windows or “RGBA” on macOS. If the bounding box is omitted, the entire screen is copied.
    while 1:
        time.sleep(0.1)
        im2 = ImageGrab.grab((x1, y1, x2, y2))
        im = ImageChops.difference(im1, im2)
        # Returns the absolute value of the pixel-by-pixel difference between the two images.
        # 마우스로 인한 변경은 반영 되지 않는다. 같은 이미지이면 difference()의 결과 이미지는 모든 픽셀이 0.
        for y in range(im.height):
            for x in range(im.width):
                if im.getpixel((x, y)) != (000): # Returns the pixel value at a given position.
                    return x, y
 
x1, y1, x2, y2 = map(int, input("Enter x1, y1, x2, y2 values: ").split())
# x1, y1, x2, y2 = input("Enter x1, y1, x2, y2 values: ").split()
# x1 = int(x1)
# y1 = int(y1)
# x2 = int(x2)
# y2 = int(y2)
 
coord = PixelCheck(x1, y1, x2, y2) # 추적할 영역의 좌상단, 우하단 좌표
print(x1 + coord[0], y1 + coord[1]) # 추적 영역 중 변화된 영역의 좌상단 좌표(스크린 기준)
cs


PixelAccess class 를 사용해 PIL.Image data를 pixel level 에서 읽어 판단하기. (쓰기도 가능)

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
from PIL import Image
from PIL import ImageGrab
from PIL import ImageChops
import time
 
def PixelCheck(x1, y1, x2, y2):
    im1 = ImageGrab.grab((x1, y1, x2, y2))
    # Take a snapshot of the screen. The pixels inside the bounding box are returned as an “RGB” image
    # on Windows or “RGBA” on macOS. If the bounding box is omitted, the entire screen is copied.
    while 1:
        time.sleep(0.1)
        im2 = ImageGrab.grab((x1, y1, x2, y2))
        im = ImageChops.difference(im1, im2)
        # Returns the absolute value of the pixel-by-pixel difference between the two images.
        # 마우스로 인한 변경은 반영 되지 않는다. 같은 이미지이면 difference()의 결과 이미지는 모든 픽셀이 0.
        px = im.load()
        # Allocates storage for the image and loads the pixel data. In normal cases, you don’t need to
        # call this method, since the Image class automatically loads an opened image when it is accessed
        # for the first time.
        for y in range(im.height):
            for x in range(im.width):
                if px[x, y] != (000):
                    return x, y
        # Accessing individual pixels is fairly slow. If you are looping over all of the pixels in an image,
        # there is likely a faster way using other parts of the Pillow API.
 
x1, y1, x2, y2 = map(int, input("Enter x1, y1, x2, y2 values: ").split())
# x1, y1, x2, y2 = input("Enter x1, y1, x2, y2 values: ").split()
# x1 = int(x1)
# y1 = int(y1)
# x2 = int(x2)
# y2 = int(y2)
 
coord = PixelCheck(x1, y1, x2, y2) # 추적할 영역의 좌상단, 우하단 좌표
print(x1 + coord[0], y1 + coord[1]) # 추적 영역 중 변화된 영역의 좌상단 좌표(스크린 기준)
cs


반응형

'Python' 카테고리의 다른 글

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
Pillow 화면 변화 감지(Pixel Checksum) 2  (0) 2018.11.21
PyMySQL  (2) 2018.11.19
Posted by J-sean
:

PyMySQL

Python 2018. 11. 19. 21:54 |
반응형

PyMySQL은 Python에서 MySQL사용을 도와주는 순수 Python MySQL client library이다.

 

설치 조건:

  • Python -- one of the following:
  • MySQL Server -- one of the following:
  • 설치:

    Package is uploaded on PyPI.

    You can install it with pip:

    $ python3 -m pip install PyMySQL

    관련 문서:

    Documentation is available online: https://pymysql.readthedocs.io/

    For support, please refer to the StackOverflow.



    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import pymysql
     
    connection = pymysql.connect(host = '127.0.0.1', port = 3306, user = 'root', password = '1234', db = 'shopdb', charset = 'utf8')
    # Representation of a socket with a mysql server. The proper way to get an instance of this class is to call connect().
    # Establish a connection to the MySQL database.
     
    cursor = connection.cursor() # Create a new cursor to execute queries with
     
    sql = "select * from membertbl"
    cursor.execute(sql) # Execute a query
     
    rows = cursor.fetchall() # Fetch all the rows
    for member in rows:
        print(member)
     
    connection.close() # Closing a cursor just exhausts all remaining data.
    cs


    반응형
    Posted by J-sean
    :