Path of Exile (POE) Inventory Automatic Orgnize !!! [1]


This posting is for educational purposes only. Never abuse, it gets misused.


If you pick up the abolition and sell the item, the Currency is piling up a lot, and today, in order to solve that problem and pick up the abolition quickly, i’ll send all the Currency to the warehouse, stash joe ~ with one Keyboard input from the character inventory. 


In POE, when you press ctrl + c against the mouse cursor on the item, is the item information copied to the Clipboard? I used the feature positively. ! For more information on how to operate, please refer to the video ~

First, let’s look at which libraries you used. 

1. Required libraries

pip install pywin32
pip install pillow
pip install numpy
pip install mss
pip install pyautogui==0.9.38
pip install opencv-python
pip install pprint


In fact, poe automatic potion eating!! If stamina half-fish … You need the same library that Post used. It’s just a new pprint. This library is intended to make python material types look better. 

2. Code 

There are some pre-work tasks that you need to do before you introduce the code. With the character inventory visible, you can change the run variables in the code below from 1 to 5 in turn and then run it!! Follow the description of each step below. 

run = 1. Find the coordinates of inventory. I need a file that I did in the last post. (Blue square screenshot)

run = 2. Save the first grid screenshot of Inventory. This screenshot is used to find an empty inventory unit, so the first inventory should be left blank and run.  

run = 3. Make sure that empty inventory units are well detected. Config.cfg (described below) if it is not detected well Try adjusting the confidence factor value!! Clipboard copytime takes quite some time, so it detects empty units and handles exceptions. 

run = 4. Make sure that the actual Currency goes well into Stash. Within 3 seconds of running the code, click on the POE game screen and make the POE an active window for normal operation. 

run = 5. Now the preparation process is over. If you press F2 during the game, move all currency from your character inventory to Stash. 

And if you look at the function below, there’s a global variable called EXCEPT_CURRENCY. This variable is a setting for Currency that will not be moved to the warehouse.

import win32clipboard
import pyautogui as pa
import mouse as mo
import keyboard as keys
import time
import numpy as np
import pprint
import cv2.cv2 as cv2
import mss
import os
from PIL import Image
K_RARENESS = '희귀도'
K_ITEMNAME = 'item_name'
EXCEPT_CURRENCY = ['Scroll of Wisdom', 'Portal Scroll']
class InventoryTool():
    itemInfoInInven = {}
    def __init__(self, inventorySize, listexceptCurr):
        # inventorySize x, y, w, h
        self.inventorySize = inventorySize
        self.inven = np.empty(shape=(12, 5), dtype=tuple)
        self.invenUnitSize = (int(inventorySize[2] / 12), int(inventorySize[2] / 12))
        self.invenUnitBox = (inventorySize[0] + 5, inventorySize[1] + 5, \
                               self.invenUnitSize[0]-5, self.invenUnitSize[1]-5)
        self.listexceptCurr = listexceptCurr
        for xunit in range(12):
            for yunit in range(5):
                x = self.inventorySize[0] + xunit * self.invenUnitSize[0]
                y = self.inventorySize[1] + yunit * self.invenUnitSize[0]
                cord =, y, self.invenUnitSize[0], self.invenUnitSize[1]))
                self.inven[xunit][yunit] = cord
    def realPoint(self, unitPointX, unitPointY):
        return (self.inven[unitPointX][unitPointY][0], self.inven[unitPointX][unitPointY][1])
    # get clipboard data
    def getItemInfoFromClipboard(self, unitPoint):
        itemInfo = {}
            itemData = win32clipboard.GetClipboardData()
            itemKinds = itemData.split('--------')[0].strip()
            rarenessAndName = itemKinds.split('\n')
            rareness_key = rarenessAndName[0].split(':')[0]
            rareness_value = rarenessAndName[0].split(':')[1]
            itemInfo[rareness_key] = rareness_value.strip()
            itemInfo[K_ITEMNAME] = rarenessAndName[1]
            self.itemInfoInInven[unitPoint] = itemInfo
            return itemInfo
            print('No Item ', unitPoint)
            return None
    def checkItemInInvertory(self, boxRegions):
        for x in range(np.shape(self.inven)[0]):
            for y in range(np.shape(self.inven)[1]):
                rpoint = self.realPoint(x, y)
                if self.checkEmptyUnitPoint(boxRegions, rpoint):
                    mo.move(rpoint[0], rpoint[1])
                    self.getItemInfoFromClipboard((x, y))
    def moveCurrencyToStash(self):'ctrl')
        for unitPoint, iteminfo in self.itemInfoInInven.items():
            rpoint = self.realPoint(unitPoint[0], unitPoint[1])
                # print('move', iteminfo[K_ITEMNAME])
                if iteminfo[K_RARENESS] == V_CURRENCY \
                        and not iteminfo[K_ITEMNAME] in self.listexceptCurr:
                    mo.move(rpoint[0], rpoint[1])
                    print('Move', iteminfo[K_ITEMNAME])
    def checkEmptyUnitPoint(self, boxRegions, centerRpoint):
        for br in boxRegions:
            x, y, w, h = br
            if (x < centerRpoint[0] < x + w) and (y < centerRpoint[1] < y + h):
                # nothing on inven
                return False
        # something on inven
        return True
    def findImage(self, templateName, show=0, confidence=0.6):
        boxRegions = []
        x, y, w, h = self.inventorySize
        mon = {'top': y, 'left': x, 'width': w, 'height': h}
        sct = mss.mss()
        img = Image.frombytes('RGB', (w, h), sct.grab(mon).rgb)
        frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        imgPath = os.path.dirname(os.path.realpath(__file__)) + '\\' + templateName
        template = cv2.imread(imgPath, 0)
        w, h = template.shape[::-1]
        res = cv2.matchTemplate(gray, template, cv2.TM_CCOEFF_NORMED)
        threshold = confidence
        loc = np.where(res >= threshold)
        for pt in zip(*loc[::-1]):
            if show == 1:
                cv2.rectangle(frame, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)
            realX = self.inventorySize[0] + pt[0]
            realY = self.inventorySize[1] + pt[1]
            boxRegions.append((realX, realY, w, h))
        if show == 1:
            cv2.imshow('image', frame)
        return boxRegions
    def makeTemplate(self, templateName, templatePoint):
        x, y, w, h = templatePoint
        mon = {'top': y, 'left': x, 'width': w, 'height': h}
        sct = mss.mss()
        img = Image.frombytes('RGB', (w, h), sct.grab(mon).rgb)
        frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
        imgPath = os.path.dirname(os.path.realpath(__file__)) + '\\' + templateName
        cv2.imwrite(imgPath, frame)
if __name__=="__main__":
    import configparser
    import cvFunc as cvf
    from ast import literal_eval
    configFile = os.path.dirname(os.path.realpath(__file__)) + '\\' + 'config.cfg'
    config = configparser.ConfigParser()
    inventory_size = literal_eval(config['inventory']['inven_region'])
    templateName = config['inventory']['inven_unit_empty_pic']
    templateConfidence = float(config['inventory']['confidence'])
    run = 1
    # -- screenshot whole inventory and get size
    if run == 1:
        ip = cvf.ScreenShot()
    # -- screenshot empty inventory unit and save
    elif run == 2:
        it = InventoryTool(inventory_size, EXCEPT_CURRENCY)
        it.makeTemplate(templateName, it.invenUnitBox)
    # -- find empty inventory unit image on whole inventory
    elif run == 3:
        it = InventoryTool(inventory_size, EXCEPT_CURRENCY)
        it.findImage(templateName, show=1, confidence=templateConfidence)
    # -- run 1 time
    elif run == 4:
        it = InventoryTool(inventory_size, EXCEPT_CURRENCY)
        boxRegions = it.findImage(templateName, 0, confidence=templateConfidence)
        # print(boxRegions)
        pprint.pprint(it.itemInfoInInven, indent=4)
    # -- run forever
    elif run == 5:
        keyState = 0
        while True:
            value = keys.is_pressed('F2')
            if value == True:
                it = InventoryTool(inventory_size, EXCEPT_CURRENCY)
                boxRegions = it.findImage(templateName, 0, confidence=templateConfidence)
                # print(boxRegions)
                pprint.pprint(it.itemInfoInInven, indent=4)
                keyState = value




3. Config.cfg

# 4K
# inven_region = (2599, 1152, 1213, 513)
# Full HD
inven_region = (1307, 576, 597, 250)
inven_unit_empty_pic = invenUnitEmpty.png
confidence = 0.8



The inventory section has been added. 

  • inven_region: means inventory x, y, w, h. You can get it as run = 1.
  • inven_unit_empty_pic: run = 2 is the name of the empty space photo of the inventory obtained. 
  • confidence: The value of openCV to allow a certain similarity to template Matching. As you get closer to 1, only the same area as the given template picture is detected. 


You can do this and run the ! 

If you have currency that doesn’t move occasionally, increase the time.sleep (0.03) time in the getItemInfoFromClipboard function to 0.05! 

If you read clipboard content too quickly after ctrl+c, you’ll see items that fall out. 


Yep today’s post is here. The code shows a very mechanical and fast mouse and keyboard movement! It’s also easy to get caught up in, so don’t abuse it or ???? I’m sorry.

I’ve built it with a dual-list namom build, but Malakai doesn’t kill…. I thought it was a mob that i’m going to die quickly, but it’s all the. !!! It’s a great place to stay.

Subscribe to the Blog!!

You may also like...

Leave a Reply

Your email address will not be published.