├── .github └── workflows │ ├── publish-ubuntu.yaml │ └── publish-windows.yaml ├── .gitignore ├── LICENSE ├── README.md ├── batch_work.py ├── custom_formatter.py ├── custom_qwidget.py ├── docs └── result.png ├── file_version_info.txt ├── models ├── detect.caffemodel ├── detect.prototxt ├── sr.caffemodel └── sr.prototxt ├── pyqt5_qr_scan.py ├── qrscan.ico ├── qrscan.png ├── requirements.txt ├── resources.py ├── resources.qrc ├── scripts ├── config_env.bat ├── config_env.sh ├── publish.bat └── publish.sh ├── sql_helper.py └── utils.py /.github/workflows/publish-ubuntu.yaml: -------------------------------------------------------------------------------- 1 | name: Ubuntu 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' 7 | tags: 8 | - '*' 9 | 10 | jobs: 11 | deploy: 12 | name: build and run 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | - uses: actions/setup-python@v4 17 | with: 18 | python-version: '3.10' 19 | architecture: 'x64' 20 | - name: download code and run 21 | env: 22 | TZ: Asia/Shanghai 23 | run: | 24 | sudo apt update && sudo apt install python3-pip python3-venv zip unzip 25 | mv scripts/config_env.sh ./ 26 | mv scripts/publish.sh ./ 27 | 28 | - name: Configure Environments 29 | run: | 30 | chmod +x config_env.sh 31 | ./config_env.sh 32 | 33 | - name: Set version 34 | if: contains(github.ref, 'tags/') 35 | run: | 36 | export VERSION="${{ github.ref_name }}" 37 | export VERSION="${VERSION#v}" 38 | export MAJOR="${VERSION%%.*}" 39 | export MINOR="${VERSION#*.}" 40 | export PATCH="${MINOR#*.}" 41 | export MINOR="${MINOR%%.*}" 42 | export HASH="${GITHUB_SHA::8}" 43 | export DATETIME=$(date +%Y%m%d%H%M) 44 | 45 | echo "VERSION=${MAJOR}.${MINOR}.${PATCH}" 46 | echo "ID=${HASH}_${DATETIME}" 47 | 48 | sed -i "s/V_MAJOR/${MAJOR}/g" file_version_info.txt 49 | sed -i "s/V_MINOR/${MINOR}/g" file_version_info.txt 50 | sed -i "s/V_PATCH/${PATCH}/g" file_version_info.txt 51 | sed -i "s/COMMIT_HASH/${HASH}/g" file_version_info.txt 52 | sed -i "s/YYYYMMDDHHMM/${DATETIME}/g" file_version_info.txt 53 | sed -i "s#setWindowTitle.*#setWindowTitle(\"图片二维码检测识别 ${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ github.ref_name }}\")#g" custom_qwidget.py 54 | 55 | 56 | - name: Publish Release 57 | run: | 58 | chmod +x publish.sh 59 | ./publish.sh 60 | 61 | - name: Upload release file 62 | if: contains(github.ref, 'tags/') 63 | uses: actions/upload-artifact@v3 64 | with: 65 | name: release 66 | path: QrScan.zip 67 | retention-days: 1 68 | 69 | 70 | upload: 71 | name: Upload Ubuntu Release 72 | runs-on: ubuntu-latest 73 | needs: deploy 74 | # 只在tag时执行,即在自己终端运行以下代码后触发 75 | # git tag -a v0.1.0 -m "release 0.1.0 version" 76 | # git push origin --tags 77 | if: contains(github.ref, 'tags/') 78 | steps: 79 | - name: Download release file 80 | uses: actions/download-artifact@v3 81 | with: 82 | name: release 83 | - name: Create Ubuntu Release 84 | run: | 85 | mv QrScan.zip QrScan_linux_${{ github.ref_name }}.zip 86 | - name: Upload Ubuntu Release 87 | uses: softprops/action-gh-release@v1 88 | with: 89 | files: QrScan_linux_${{ github.ref_name }}.zip -------------------------------------------------------------------------------- /.github/workflows/publish-windows.yaml: -------------------------------------------------------------------------------- 1 | name: Windows 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' 7 | tags: 8 | - '*' 9 | 10 | jobs: 11 | deploy: 12 | name: build and run 13 | runs-on: windows-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | - uses: actions/setup-python@v4 17 | with: 18 | python-version: '3.10' 19 | architecture: 'x64' 20 | - name: download code and run 21 | env: 22 | TZ: Asia/Shanghai 23 | run: | 24 | move scripts/config_env.bat ./ 25 | move scripts/publish.bat ./ 26 | 27 | - name: Configure Environments 28 | run: | 29 | ./config_env.bat 30 | 31 | - name: Set version 32 | shell: bash 33 | run: | 34 | if [[ "${{ github.ref }}" == "refs/tags/"* ]]; then 35 | export VERSION="${{ github.ref_name }}" 36 | else 37 | export VERSION="v0.0.0" 38 | fi 39 | export VERSION="${VERSION#v}" 40 | export MAJOR="${VERSION%%.*}" 41 | export MINOR="${VERSION#*.}" 42 | export PATCH="${MINOR#*.}" 43 | export MINOR="${MINOR%%.*}" 44 | export HASH="${GITHUB_SHA::8}" 45 | export DATETIME=$(date +%Y%m%d%H%M) 46 | 47 | echo "VERSION=${MAJOR}.${MINOR}.${PATCH}" 48 | echo "ID=${HASH}_${DATETIME}" 49 | 50 | sed -i "s/V_MAJOR/${MAJOR}/g" file_version_info.txt 51 | sed -i "s/V_MINOR/${MINOR}/g" file_version_info.txt 52 | sed -i "s/V_PATCH/${PATCH}/g" file_version_info.txt 53 | sed -i "s/COMMIT_HASH/${HASH}/g" file_version_info.txt 54 | sed -i "s/YYYYMMDDHHMM/${DATETIME}/g" file_version_info.txt 55 | sed -i "s#setWindowTitle.*#setWindowTitle(\"图片二维码检测识别 ${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ github.ref_name }}\")#g" custom_qwidget.py 56 | 57 | - name: Publish Release 58 | run: | 59 | ./publish.bat 60 | 61 | - name: Upload release file 62 | uses: actions/upload-artifact@v3 63 | with: 64 | name: release 65 | path: QrScan.zip 66 | retention-days: 1 67 | 68 | upload: 69 | name: Upload Windows Release 70 | runs-on: ubuntu-latest 71 | needs: deploy 72 | # 只在tag时执行,即在自己终端运行以下代码后触发 73 | # git tag -a v0.1.0 -m "release 0.1.0 version" 74 | # git push origin --tags 75 | if: contains(github.ref, 'tags/') 76 | steps: 77 | - name: Download release file 78 | uses: actions/download-artifact@v3 79 | with: 80 | name: release 81 | - name: Create Windows Release 82 | run: | 83 | mv QrScan.zip QrScan_windows_${{ github.ref_name }}.zip 84 | - name: Upload Windows Release 85 | uses: softprops/action-gh-release@v1 86 | with: 87 | files: QrScan_windows_${{ github.ref_name }}.zip -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | [Ll]og/ 6 | *.db 7 | *.bat 8 | *.sh 9 | *.zip 10 | 11 | # C extensions 12 | *.so 13 | 14 | # Distribution / packaging 15 | .Python 16 | bin/ 17 | build/ 18 | develop-eggs/ 19 | dist/ 20 | downloads/ 21 | eggs/ 22 | .eggs/ 23 | lib/ 24 | lib64/ 25 | parts/ 26 | sdist/ 27 | var/ 28 | wheels/ 29 | pip-wheel-metadata/ 30 | share/python-wheels/ 31 | *.egg-info/ 32 | .installed.cfg 33 | *.egg 34 | MANIFEST 35 | 36 | # PyInstaller 37 | # Usually these files are written by a python script from a template 38 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 39 | *.manifest 40 | *.spec 41 | 42 | # Installer logs 43 | pip-log.txt 44 | pip-delete-this-directory.txt 45 | 46 | # Unit test / coverage reports 47 | htmlcov/ 48 | .tox/ 49 | .nox/ 50 | .coverage 51 | .coverage.* 52 | .cache 53 | nosetests.xml 54 | coverage.xml 55 | *.cover 56 | *.py,cover 57 | .hypothesis/ 58 | .pytest_cache/ 59 | 60 | # Translations 61 | *.mo 62 | *.pot 63 | 64 | # Django stuff: 65 | *.log 66 | local_settings.py 67 | db.sqlite3 68 | db.sqlite3-journal 69 | 70 | # Flask stuff: 71 | instance/ 72 | .webassets-cache 73 | 74 | # Scrapy stuff: 75 | .scrapy 76 | 77 | # Sphinx documentation 78 | docs/_build/ 79 | 80 | # PyBuilder 81 | target/ 82 | 83 | # Jupyter Notebook 84 | .ipynb_checkpoints 85 | 86 | # IPython 87 | profile_default/ 88 | ipython_config.py 89 | 90 | # pyenv 91 | .python-version 92 | 93 | # pipenv 94 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 95 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 96 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 97 | # install all needed dependencies. 98 | #Pipfile.lock 99 | 100 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 101 | __pypackages__/ 102 | 103 | # Celery stuff 104 | celerybeat-schedule 105 | celerybeat.pid 106 | 107 | # SageMath parsed files 108 | *.sage.py 109 | 110 | # Environments 111 | .env 112 | .venv 113 | env/ 114 | venv/ 115 | ENV/ 116 | env.bak/ 117 | venv.bak/ 118 | 119 | # Spyder project settings 120 | .spyderproject 121 | .spyproject 122 | 123 | # Rope project settings 124 | .ropeproject 125 | 126 | # mkdocs documentation 127 | /site 128 | 129 | # mypy 130 | .mypy_cache/ 131 | .dmypy.json 132 | dmypy.json 133 | 134 | # Pyre type checker 135 | .pyre/ 136 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QrScan 2 | 二维码图片批量检测识别软件 3 | 支持常见的图片文件:`jpg`、`jpeg`、`png`、`bmp`、`tif`、`tiff`、`pbm`、`pgm`、`ppm`、`ras`等(识别二维码根据的是文件内容,即使扩展名为其他的,只要文件内容是图片编码都可识别) 4 | **Win7及以下系统**可能存在兼容性问题 5 | 6 | 软件截图 7 | 软件截图 8 | 9 | ## 1. 功能 10 | * 完全**离线**的软件,升级和更新在GitHub查看 11 | * 能够批量排查图片是否包含二维码以及识别二维码链接 12 | * 支持文件夹导入排查范围,自动遍历所有子文件夹 13 | * 支持拖放文件夹到程序的输入框 14 | * 支持选择对包含二维码图片进行的操作:**删除**、**剪切**、**识别** 15 | * 对于剪切操作,需要设置保存剪切文件的文件夹,遇到文件重名将会按时间戳重命名 16 | * 对于识别操作,需要设置保存二维码识别结果的文件夹,结果自动保存在该目录的`qrcode.csv`文件 17 | * 支持`启动`、`暂停`、`继续`、`停止`四种操作 18 | * 支持继续上次的任务(关闭软件前的任务未完成) 19 | * 支持实时日志显示与进度展示 20 | * 支持文件日志记录,默认保存在程序目录下的`log`文件夹,文件名格式为`年月日时分秒毫秒.txt` 21 | * 对于剪切和删除操作,默认会在日志文件夹中保存二维码识别结果,文件名格式为`年月日时分秒毫秒.csv` 22 | * 支持多进程极速检测识别 23 | 24 | ## 2. 下载软件 25 | ### 2.1. 使用已经编译成功的发布版软件 26 | 下载地址:[release](https://github.com/zfb132/QrScan/releases) 27 | 建议解压后的程序放置在**不需要管理员权限的目录**下,否则可能会出现无法写入日志文件的问题 28 | 若某一个版本出现问题,可以尝试下载其他版本 29 | 30 | ### 2.2. 从代码编译运行打包软件 31 | 根据本机系统平台的不同,选择不同的文件后缀名: `Windows`平台选择`.bat`,`Linux`平台选择`.sh` 32 | * 把`scripts/config_env`和`scripts/publish`移动到当前目录 33 | * 执行`config_env` 34 | * 在`Windows`系统此时可以通过命令`.\venv\Scripts\python.exe pyqt5_qr_scan.py`运行本软件;在`Linux`系统此时可以通过命令`venv/bin/python3 pyqt5_qr_scan.py`运行本软件 35 | * 如要打包软件(剥离python环境),则执行`publish`,最终会在当前目录得到一个`QrScan.zip`压缩包 36 | 37 | ## 3. 免责声明 38 | 一切下载及使用本软件时均被视为已经仔细阅读并完全同意以下条款: 39 | * 软件仅供个人学习与交流使用,严禁用于非法用途,转载需申请作者授权 40 | * 严禁未经书面许可用于商业用途 41 | * 使用本软件所存在的风险将完全由其本人承担,软件作者不承担任何责任 42 | * 软件注明之服务条款外,其它因不当使用软件而导致的任何意外、疏忽、合约毁坏、诽谤、版权或其他知识产权侵犯及其所造成的任何损失,软件作者不承担任何法律责任 43 | * 本声明未涉及的问题请参见国家有关法律法规,当本声明与国家有关法律法规冲突时,以国家法律法规为准 44 | * 本软件相关声明版权及其修改权、更新权和最终解释权均属软件作者所有 -------------------------------------------------------------------------------- /batch_work.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # author: 'zfb' 4 | # time: 2022-05-03 18:02 5 | 6 | import logging 7 | from datetime import datetime 8 | from cv2 import imdecode, cvtColor, IMREAD_UNCHANGED, COLOR_GRAY2RGB, COLOR_RGBA2RGB, wechat_qrcode_WeChatQRCode 9 | from numpy import fromfile, uint8, uint16 10 | from shutil import move 11 | from sys import exit 12 | 13 | from multiprocessing import Event, cpu_count, Pool 14 | from os.path import join, dirname, basename, exists, splitext, normpath 15 | from os import walk, remove 16 | from PyQt5.QtCore import QObject, pyqtSignal 17 | 18 | from sql_helper import insert_file, insert_status, clean_files_table, clean_status_table, get_all_files 19 | from utils import get_base_path 20 | 21 | def setup_event(event): 22 | global unpaused 23 | unpaused = event 24 | 25 | try: 26 | # 使用opencv的wechat_qrcode模块创建二维码识别器 27 | # https://github.com/WeChatCV/opencv_3rdparty/tree/wechat_qrcode 28 | model_base_path = join(get_base_path(), "models") 29 | detector = wechat_qrcode_WeChatQRCode( 30 | join(model_base_path, "detect.prototxt"), join(model_base_path, "detect.caffemodel"), 31 | join(model_base_path, "sr.prototxt"), join(model_base_path, "sr.caffemodel") 32 | ) 33 | # print("创建识别器成功") 34 | except Exception as e: 35 | print(repr(e)) 36 | print("初始化识别器失败!") 37 | exit(0) 38 | 39 | def convert_to_8bit_rgb(img): 40 | """ 41 | 将图像转换为8位RGB格式。 42 | 如果图像已经是8位RGB,则不进行任何操作。 43 | """ 44 | # 如果图像是灰度图,转换为RGB 45 | if len(img.shape) == 2: 46 | img = cvtColor(img, COLOR_GRAY2RGB) 47 | 48 | # 如果图像是16位深度,转换为8位 49 | elif img.dtype == uint16: 50 | img = (img / 256).astype(uint8) 51 | 52 | # 如果图像是RGBA,转换为RGB 53 | elif img.shape[2] == 4: 54 | img = cvtColor(img, COLOR_RGBA2RGB) 55 | 56 | return img 57 | 58 | def scan(img_name, cut_path, operation): 59 | ''' 60 | @param img_name 图片文件的名称 61 | @param cut_path 准备存放包含二维码图片的路径 62 | @operation 对包含二维码的图片要进行的操作。 63 | 'cut'表示剪切到cut_path文件夹,'delete'表示删除该图片,'decode'表示识别二维码 64 | @return [img_status, op_status, qrcode] 65 | 66 | img_status: 67 | None表示遇到未知问题 68 | 1表示输入文件是包含二维码的图片\n 69 | 2表示输入文件是不包含二维码的图片\n 70 | 3表示输入文件不是一个合法图片\n 71 | 4表示输入文件不是一个图片\n 72 | 73 | op_status: 74 | None表示遇到未知问题 75 | 1表示文件剪切成功 76 | 2表示文件剪切失败 77 | 3表示文件删除成功 78 | 4表示文件删除失败 79 | 5表示文件已有重名,添加时间戳后剪切成功 80 | 6表示文件有重名,且添加时间戳后也失败 81 | 7表示对文件不进行任何操作 82 | 8表示文件识别成功 83 | ''' 84 | img_status = None 85 | op_status = None 86 | # [图片名称, [二维码]] 87 | qrcode = None 88 | # 处理过程中的运行信息 89 | note = None 90 | full_name = img_name 91 | # imread不支持中文路径 92 | # img = imread(img_name) 93 | npfile = fromfile(img_name, dtype=uint8) 94 | if npfile.size == 0: 95 | note = f"空白文件: {img_name}" 96 | logging.error(note) 97 | return [4, op_status, [full_name, qrcode], note] 98 | img = imdecode(npfile, IMREAD_UNCHANGED) 99 | if img is None: 100 | note = f"不是图片: {img_name}" 101 | logging.warning(note) 102 | return [4, op_status, [full_name, qrcode], note] 103 | # if img.empty(): 104 | if img.size == 0 : 105 | note = f"空白图片: {img_name} 不是一个合法图片!" 106 | logging.error(note) 107 | return [3, op_status, [full_name, qrcode], note] 108 | try: 109 | img = convert_to_8bit_rgb(img) 110 | res, points = detector.detectAndDecode(img) 111 | except Exception as e: 112 | print(repr(e)) 113 | note = f"识别失败: {img_name} 识别失败!" 114 | return [None, op_status, [full_name, qrcode], note] 115 | # res=None res=() res=("") 116 | if res == None or len(res) < 1 or (len(res) == 1 and not res[0]): 117 | note = f"无二维码: {img_name}" 118 | logging.info(note) 119 | img_status = 2 120 | op_status = 7 121 | return [img_status, op_status, [full_name, qrcode], note] 122 | else: 123 | logging.debug(f"{img_name} 检测到二维码") 124 | img_status = 1 125 | if operation == 'cut': 126 | new_name = join(cut_path, basename(img_name)) 127 | file_exist = False 128 | try: 129 | if not exists(new_name): 130 | move(img_name, new_name) 131 | note = f"直接剪切: {img_name}--->{new_name}" 132 | logging.debug(note) 133 | op_status = 1 134 | else: 135 | file_exist = True 136 | logging.warning(f"文件{img_name}已存在!") 137 | except Exception as e: 138 | logging.error(repr(e)) 139 | note = f"剪切失败: {img_name} 直接剪切失败!" 140 | logging.error(note) 141 | op_status = 2 142 | if file_exist: 143 | time_str = datetime.now().strftime("_%Y%m%d%H%M%S%f") 144 | m = splitext(new_name) 145 | new_name = m[0] + time_str + m[1] 146 | try: 147 | move(img_name, new_name) 148 | note = f"重名剪切: {img_name}--->{new_name}" 149 | logging.debug(note) 150 | op_status = 5 151 | except Exception as e: 152 | logging.error(repr(e)) 153 | note = f"剪切失败: {img_name} 重命名后剪切失败!" 154 | logging.error(note) 155 | op_status = 6 156 | elif operation == 'delete': 157 | try: 158 | remove(img_name) 159 | note = f"删除成功: {img_name}" 160 | logging.debug(note) 161 | op_status = 3 162 | except Exception as e: 163 | logging.error(repr(e)) 164 | note = f"删除失败: {img_name}" 165 | logging.error(note) 166 | op_status = 4 167 | elif operation == 'decode': 168 | op_status = 8 169 | note = f"识别成功: {img_name}" 170 | qrcode = [full_name, res] 171 | return [img_status, op_status, qrcode, note] 172 | 173 | 174 | def scan_process(pathes, cut_path, operation): 175 | '''批次任务启动过程中的中转函数 176 | ''' 177 | results = [] 178 | for path in pathes: 179 | unpaused.wait() 180 | results.append(scan(path, cut_path, operation)) 181 | return results 182 | 183 | class BatchWork(QObject): 184 | '''具体的多进程工作处理的类,通过构造函数接收参数和任务处理的函数 185 | ''' 186 | # 信号量,负责实现外部进程更新UI进程的界面显示 187 | # UI进程的界面显示只能在UI主进程里面进行,所以这里触发信号,并传递参数 188 | # 前往信号对应的槽函数,进行处理 189 | # 该信号用于触发和传递任务的执行进度(并非实时,只能每批任务执行完毕,统一更新) 190 | notifyProgress = pyqtSignal(int) 191 | # 该信号用于指示目前的工作状态,控制按钮的启用与否(保证任务运行过程中不会再次运行) 192 | notifyStatus = pyqtSignal(bool) 193 | 194 | def __init__(self, myvar, func): 195 | '''通过构造函数的myvar变量接收参数\n 196 | 通过func函数接收具体用于任务处理的函数 197 | ''' 198 | self.work = func 199 | self.var = myvar[:3] 200 | self.log_file = myvar[3] 201 | self.is_first = myvar[4] 202 | super(BatchWork, self).__init__() 203 | 204 | def chunks(self, l, n): 205 | '''此函数用于配合实现列表分割 206 | ''' 207 | for i in range(0, len(l), n): 208 | yield l[i:i + n] 209 | 210 | def resize_list(self, data_list, group_size): 211 | '''将一维列表按照指定长度分割 212 | ''' 213 | data_chunks = list(self.chunks(data_list, group_size)) 214 | results = [] 215 | for i in range(len(data_chunks)): 216 | results.append(data_chunks[i]) 217 | return results 218 | 219 | def show_info(self, img_status, op_status, name): 220 | '''根据返回的状态码显示不同的日志内容 221 | ''' 222 | if img_status is None: 223 | logging.error(f"{name}出现未知错误!") 224 | return 225 | elif img_status == 1: 226 | logging.debug(f"{name}检测到二维码") 227 | elif img_status == 2: 228 | logging.info(f"{name}不包含二维码") 229 | elif img_status == 3: 230 | logging.warning(f"{name}不是一个合法图片!") 231 | return 232 | elif img_status == 4: 233 | logging.warning(f"{name}不是一个图片!") 234 | return 235 | else: 236 | logging.error(f"{name}程序出现bug!") 237 | return 238 | if op_status is None: 239 | logging.error(f"{name}出现未知错误!") 240 | elif op_status == 1: 241 | logging.debug(f"{name}剪切成功") 242 | elif op_status == 2: 243 | logging.error(f"{name}剪切失败!") 244 | elif op_status == 3: 245 | logging.debug(f"{name}删除成功") 246 | elif op_status == 4: 247 | logging.error(f"{name}删除失败!") 248 | elif op_status == 5: 249 | logging.debug(f"{name}重名,添加时间戳后剪切成功") 250 | elif op_status == 6: 251 | logging.error(f"{name}重名,添加时间戳后剪切仍然失败!") 252 | elif op_status == 7: 253 | pass 254 | elif op_status == 8: 255 | logging.debug(f"{name}识别二维码成功") 256 | else: 257 | logging.error(f"{name}程序出现bug!") 258 | 259 | def save_qrcode(self, path, qrcode, is_log=False): 260 | if is_log: 261 | pure_log_name = basename(self.log_file.name).split('.')[:-1] 262 | name = join(path, f"{'.'.join(pure_log_name)}.csv") 263 | else: 264 | name = join(path, "qrcode.csv") 265 | flag = False 266 | with open(name, "a", encoding="utf-8-sig", errors="replace") as f: 267 | for single_res in qrcode: 268 | if single_res is None: 269 | continue 270 | f.write(f'"{single_res[0]}",{",".join(single_res[1])}\n') 271 | flag = True 272 | if flag: 273 | logging.debug(f"识别二维码结果保存到文件{name}成功!") 274 | 275 | def filter_names(self, pathes): 276 | ''' 277 | 从数据库中读取已经识别过的文件,将其从pathes中删除 278 | ''' 279 | db_normpath_names = [x[0] for x in get_all_files()] 280 | # item in new_lists but not in db_normpath_names 281 | return list(set(pathes) - set(db_normpath_names)) 282 | 283 | def run(self): 284 | # 使用信号槽机制,禁用按钮,因为此时已经开始处理 285 | # 防止用户再次提交任务 286 | self.notifyStatus.emit(True) 287 | logging.info('开始进行检测') 288 | # 读取参数 289 | path, cut_path, operation = self.var 290 | # 传入的path和cut_path已经是normpath 291 | # path = os.path.normpath(path) 292 | # 读取path及其子目录下的所有文件(所有扩展名)并存入m*2*n列表 293 | pathes = [] 294 | for root, dirs, files in walk(path): 295 | # for dir_name in dirs: 296 | # rename_func(root, dir_name) 297 | for file_name in files: 298 | pathes.append(normpath(join(root, file_name))) 299 | if not self.is_first: 300 | logging.info("检测到上次运行未结束,将过滤已经识别过的文件") 301 | pathes = self.filter_names(pathes) 302 | logging.info(f"载入所有{len(pathes)}个文件成功!") 303 | # 根据CPU核心数量开启多进程,充分利用资源 304 | pro_cnt = cpu_count() 305 | # 按照每组100个进行分割 306 | # group_size = 100 307 | # if len(pathes) < 1000: 308 | # group_size = len(pathes)//(2*pro_cnt) 309 | # if group_size < 1: 310 | # group_size = 1 311 | # 还是默认8个吧,否则一个批次的任务执行时间太久,日志和进度条会好久才动 312 | group_size = 4 313 | # 把m*2*n的列表分割成新列表,新列表的前面t-1元素都是group_size*2*n 314 | # 最后一个元素[len(pathes)-(t-1)*group_size]X2Xn 315 | final_pathes = self.resize_list(pathes, group_size) 316 | # 最终创建进程的数量(一般远大于进程池的大小) 317 | num_procs = len(final_pathes) 318 | # 用于存放多进程返回结果的列表 319 | results = list(range(num_procs)) 320 | insert_status(operation, path, cut_path, 0) 321 | # 创建进程池 322 | self.event = Event() 323 | self.pool = Pool(processes=pro_cnt, initializer=setup_event, initargs=(self.event,)) 324 | # 开始逐个将进程加入进程池 325 | for i in range(num_procs): 326 | params = final_pathes[i] 327 | # 维持执行的进程总数为processes,当一个进程执行完毕后会添加新的进程进去 328 | results[i] = self.pool.apply_async(func=self.work, args=(params, cut_path, operation,)) 329 | logging.info(f"创建{num_procs}个进程,进程池大小:{pro_cnt}") 330 | self.pool.close() 331 | # unpause workers 332 | self.event.set() 333 | # 调用join之前,先调用close函数,否则会出错。 334 | # 执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束 335 | # pool.join() 336 | # 用于统计含有二维码图片的数量 337 | qr_img_num = 0 338 | # 用于统计操作成功的次数(包含剪切成功、删除成功、添加时间戳后剪切成功) 339 | op_success_num = 0 340 | for i in range(len(results)): 341 | qrcode = [] 342 | # 每个批次执行完毕才会进来 343 | m = results[i].get() 344 | # 格式化输出结果 345 | for t in range(len(m)): 346 | img_status, op_status, qrcode_thread, note = m[t] 347 | name = qrcode_thread[0] 348 | insert_file(name) 349 | if img_status == 1: 350 | qr_img_num += 1 351 | # 剪切成功、删除成功、添加时间戳后剪切成功 352 | if op_status in [1,3,5,8]: 353 | op_success_num += 1 354 | qrcode.append(qrcode_thread) 355 | # 显示每个批次的日志 356 | self.show_info(img_status, op_status, name) 357 | # 写入日志文件 358 | if self.log_file: 359 | self.log_file.write(f"{note}\n") 360 | if self.log_file: 361 | self.log_file.flush() 362 | # 更新进度条(进度条的上限初始化为100) 363 | if operation == "decode": 364 | self.save_qrcode(cut_path, qrcode) 365 | else: 366 | if self.log_file: 367 | self.save_qrcode(join(get_base_path(), "log"), qrcode, self.log_file) 368 | self.notifyProgress.emit((i+1)*100//num_procs) 369 | # logging.info(f"进程{i}结束") 370 | logging.info(f"扫描任务结束:") 371 | logging.info(f"共计检测到{qr_img_num}个包含二维码的图片,其中{op_success_num}个文件执行操作成功") 372 | # 清空files.db 373 | clean_files_table() 374 | # 保存操作记录 375 | clean_status_table() 376 | if self.log_file: 377 | self.log_file.close() 378 | # 使用信号槽机制,启用按钮,因为任务已经处理完成 379 | # 用户可以再次提交任务或创建新任务 380 | self.notifyStatus.emit(False) 381 | -------------------------------------------------------------------------------- /custom_formatter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # author: 'zfb' 4 | # time: 2022-05-03 18:02 5 | 6 | import logging 7 | 8 | from PyQt5.QtGui import QColor 9 | 10 | class CustomFormatter(logging.Formatter): 11 | '''自定义日志的格式化,保证QPlainTextEdit可以用不同颜色显示对应等级的日志 12 | ''' 13 | # 定义不同日志等级的格式和颜色 14 | FORMATS = { 15 | # critical专门用于显示其他信息,所以不需要时间日期 16 | logging.CRITICAL: ("[{asctime}]: {message}", "#000000"), 17 | logging.ERROR: ("[{asctime}] {levelname:-<8}--- {message}", QColor("red")), 18 | logging.DEBUG: ("[{asctime}] {levelname:-<8}--- {message}", "green"), 19 | logging.INFO: ("[{asctime}] {levelname:-<8}--- {message}", "#0000FF"), 20 | logging.WARNING: ('[{asctime}] {levelname:-<8}--- {message}', QColor(100, 100, 0)) 21 | } 22 | 23 | def __init__(self): 24 | '''把格式化设置为{}风格,而不是()%s,从子类修改父类 25 | ''' 26 | super().__init__(style="{") 27 | 28 | def format(self, record): 29 | '''继承logging.Formatter必须实现的方法 30 | ''' 31 | last_fmt = self._style._fmt 32 | opt = CustomFormatter.FORMATS.get(record.levelno) 33 | # 设置时间日期的格式化规则 34 | self.datefmt = "%Y-%m-%d %H:%M:%S" 35 | if opt: 36 | fmt, color = opt 37 | self._style._fmt = "{}".format(QColor(color).name(),fmt) 38 | res = logging.Formatter.format(self, record) 39 | self._style._fmt = last_fmt 40 | return res -------------------------------------------------------------------------------- /custom_qwidget.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # author: 'zfb' 4 | # time: 2022-05-03 18:02 5 | 6 | import logging 7 | 8 | from os.path import isdir, normpath, exists 9 | from PyQt5.QtCore import QObject, QThread, pyqtSignal 10 | from PyQt5.QtWidgets import (QApplication, QPlainTextEdit, QDialog, QGridLayout, 11 | QProgressBar, QPushButton, QRadioButton, QSizePolicy, QStyleFactory, 12 | QFileDialog, QMessageBox, QLineEdit, QVBoxLayout, QHBoxLayout, QGroupBox) 13 | 14 | from custom_formatter import CustomFormatter 15 | from batch_work import BatchWork, scan_process 16 | from os import makedirs, path 17 | from datetime import datetime 18 | 19 | from sql_helper import get_status, clean_files_table, clean_status_table 20 | from utils import get_base_path 21 | 22 | class QPlainTextEditLogger(QObject, logging.Handler): 23 | '''自定义Qt控件,继承自QObject,初始化时创建QPlainTextEdit控件\n 24 | 用于实现QPlainTextEdit的日志输出功能 25 | ''' 26 | # 信号量,负责实现外部进程更新UI进程的界面显示 27 | # UI进程的界面显示只能在UI主进程里面进行,所以这里触发信号,并传递参数 28 | # 前往信号对应的槽函数,进行处理 29 | # 该信号用于触发和传递日志信息 30 | new_record = pyqtSignal(object) 31 | 32 | def __init__(self, parent=None): 33 | super().__init__() 34 | self.widget = QPlainTextEdit(parent) 35 | self.widget.setReadOnly(True) 36 | 37 | def emit(self, record): 38 | msg = self.format(record) 39 | self.new_record.emit(msg) 40 | 41 | 42 | class QDropLineEdit(QLineEdit): 43 | '''用于实现拖放文件夹到编辑框的功能\n 44 | 自定义Qt控件,继承自QLineEdit 45 | ''' 46 | def dragEnterEvent(self, event): 47 | if event.mimeData().hasUrls(): 48 | event.acceptProposedAction() 49 | 50 | def dropEvent(self, event): 51 | md = event.mimeData() 52 | if md.hasUrls(): 53 | files = [url.toLocalFile() for url in md.urls()] 54 | # 只接受文件夹的拖放 55 | files = [x for x in files if isdir(normpath(x))] 56 | num = len(files) 57 | if num > 1: 58 | logging.warning(f"检测到多条数据,只读取第一个!") 59 | elif num == 0: 60 | logging.warning(f"请确保拖放文件夹而不是文件!") 61 | return 62 | self.setText(files[0]) 63 | event.acceptProposedAction() 64 | 65 | 66 | class QrDetectDialog(QDialog): 67 | '''Qt界面的主窗体,继承自QDialog 68 | ''' 69 | def __init__(self, parent=None): 70 | super(QrDetectDialog, self).__init__(parent) 71 | 72 | # 用于写入日志到QPlainTextEdit 73 | self.logger = QPlainTextEditLogger() 74 | logging.getLogger().addHandler(self.logger) 75 | # 设置日志的格式化类 76 | self.logger.setFormatter(CustomFormatter()) 77 | # 设置日志的记录等级,低于该等级的日志将不会输出 78 | logging.getLogger().setLevel(logging.DEBUG) 79 | # 信号槽绑定,绑定在QPlainTextEditLogger创建的new_record信号到该函数 80 | self.logger.new_record.connect(self.logger.widget.appendHtml) 81 | self._loadThread = None 82 | self.run_func = None 83 | self.log_file = None 84 | 85 | # 界面基本元素创建 86 | self.createBottomLeftGroupBox() 87 | self.createTopLeftGroupBox() 88 | self.createControlGroupBox() 89 | self.createRightGroupBox(self.logger.widget) 90 | self.createProgressBar() 91 | 92 | # 用于在pyqt5中的一个线程中,开启多进程 93 | self.runButton.clicked.connect(self.batch_work) 94 | self.pauseButton.clicked.connect(self.pause_batch_work) 95 | self.resumeButton.clicked.connect(self.resume_batch_work) 96 | self.stopButton.clicked.connect(self.stop_batch_work) 97 | self.radioButton1.clicked.connect(self.disableCutPathStatus) 98 | self.radioButton2.clicked.connect(self.clickCutRadioButton) 99 | self.radioButton3.clicked.connect(self.clickDecodeRadioButton) 100 | self.imgPathButton.clicked.connect(self.get_img_path) 101 | self.cutPathButton.clicked.connect(self.get_cut_path) 102 | 103 | # 主界面布局搭建,网格布局 104 | mainLayout = QGridLayout() 105 | # addWidget(QWidget, row: int, column: int, rowSpan: int, columnSpan: int) 106 | mainLayout.addWidget(self.topLeftGroupBox, 1, 0) 107 | mainLayout.addWidget(self.bottomLeftGroupBox, 0, 0) 108 | mainLayout.addWidget(self.controlGroupBox, 2, 0) 109 | mainLayout.addWidget(self.rightGroupBox, 0, 1, 3, 1) 110 | mainLayout.addWidget(self.progressBar, 3, 0, 1, 2) 111 | # 设置每一列的宽度比例,第0列的宽度为1;第1列的宽度为2 112 | mainLayout.setColumnStretch(0, 1) 113 | mainLayout.setColumnStretch(1, 2) 114 | # 设置每一行的宽度比例,第0行的宽度为1;第1行的宽度为2 115 | mainLayout.setRowStretch(0, 1) 116 | mainLayout.setRowStretch(1, 1) 117 | mainLayout.setRowStretch(2, 2) 118 | self.setLayout(mainLayout) 119 | 120 | self.setWindowTitle("图片二维码检测识别 github.com/zfb132/QrScan") 121 | self.changeStyle('WindowsVista') 122 | self.load_exists() 123 | 124 | def load_exists(self): 125 | self.is_first = True 126 | res = get_status() 127 | if res: 128 | self.is_first = False 129 | # 弹窗询问是否继续上次的操作 130 | reply = QMessageBox.question(self, '提示', '检测到上次未完成的操作,是否继续?', QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) 131 | if reply == QMessageBox.No: 132 | clean_files_table() 133 | clean_status_table() 134 | return 135 | operation, img_path, cut_path = res 136 | if operation == "delete": 137 | self.radioButton1.setChecked(True) 138 | self.radioButton2.setChecked(False) 139 | self.radioButton3.setChecked(False) 140 | elif operation == "cut": 141 | self.radioButton2.setChecked(True) 142 | self.radioButton1.setChecked(False) 143 | self.radioButton3.setChecked(False) 144 | elif operation == "decode": 145 | self.radioButton3.setChecked(True) 146 | self.radioButton1.setChecked(False) 147 | self.radioButton2.setChecked(False) 148 | if img_path: 149 | self.imgPathTextBox.setText(img_path) 150 | if cut_path: 151 | self.cutPathTextBox.setText(cut_path) 152 | logging.info(f"上次未完成的操作为:{operation}") 153 | logging.info(f"图片路径为:{img_path}") 154 | logging.info(f"保存路径为:{cut_path}") 155 | 156 | 157 | def set_run_func(self, func): 158 | self.run_func = func 159 | 160 | def get_img_path(self): 161 | directory = QFileDialog.getExistingDirectory(self, "选取图片所在的文件夹") 162 | self.imgPathTextBox.setText(directory) 163 | 164 | def get_cut_path(self): 165 | directory = QFileDialog.getExistingDirectory(self, "选取保存结果的文件夹") 166 | self.cutPathTextBox.setText(directory) 167 | 168 | def set_log_file(self): 169 | log_name = path.join(get_base_path(), "log", f"{datetime.now().strftime('%Y%m%d%H%M%S')}.txt") 170 | try: 171 | self.log_file = open(log_name, "w", encoding="utf-8") 172 | logging.info(f"日志文件{log_name}创建成功") 173 | except Exception as e: 174 | logging.warning(f"日志文件{log_name}创建失败") 175 | logging.warning(repr(e)) 176 | 177 | def batch_work(self): 178 | # 运行按钮的响应函数 179 | # 获取操作类型,cut还是delete 180 | operation = 'cut' 181 | if self.radioButton1.isChecked(): 182 | operation = 'delete' 183 | if self.radioButton2.isChecked(): 184 | operation = 'cut' 185 | if self.radioButton3.isChecked(): 186 | operation = 'decode' 187 | c1 = self.imgPathTextBox.text().strip() 188 | if not c1: 189 | QMessageBox.warning(self, '警告', f'请先设置图片所在文件夹!', QMessageBox.Yes) 190 | return 191 | # 保证路径都是标准格式 192 | img_path = normpath(c1) 193 | if not exists(img_path): 194 | QMessageBox.warning(self, '警告', f'不存在路径:{img_path}', QMessageBox.Yes) 195 | return 196 | cut_path = "" 197 | if operation != 'delete': 198 | c2 = self.cutPathTextBox.text().strip() 199 | if not c2: 200 | msg = "请先设置保存二维码图片的文件夹!" 201 | if operation == 'decode': 202 | msg = "请先设置保存二维码识别结果的文件夹!" 203 | QMessageBox.warning(self, '警告', f'{msg}', QMessageBox.Yes) 204 | return 205 | cut_path = normpath(c2) 206 | if not exists(cut_path): 207 | QMessageBox.warning(self, '警告', f'不存在路径:{img_path}', QMessageBox.Yes) 208 | return 209 | # 设置默认日志 210 | self.logger.widget.setPlainText("") 211 | logging.critical("作者:zfb") 212 | logging.critical("https://github.com/zfb132/QrScan") 213 | # 创建线程 214 | self._loadThread=QThread(parent=self) 215 | self.set_log_file() 216 | # vars = [1, 2, 3, 4, 5, 6]*6 217 | vars = [img_path, cut_path, operation, self.log_file, self.is_first] 218 | self.loadThread=BatchWork(vars, self.run_func) 219 | # 为BatchWork类的两个信号绑定槽函数 220 | self.loadThread.notifyProgress.connect(self.updateProgressBar) 221 | self.loadThread.notifyStatus.connect(self.updateButtonStatus) 222 | # 用于开辟新进程,不阻塞主界面 223 | self.loadThread.moveToThread(self._loadThread) 224 | self._loadThread.started.connect(self.loadThread.run) 225 | self._loadThread.start() 226 | 227 | def pause_batch_work(self): 228 | if self.loadThread: 229 | self.loadThread.event.clear() 230 | logging.critical("暂停运行!") 231 | self.resumeButton.setDisabled(False) 232 | self.pauseButton.setDisabled(True) 233 | 234 | def resume_batch_work(self): 235 | if self.loadThread: 236 | self.loadThread.event.set() 237 | logging.critical("继续运行!") 238 | self.resumeButton.setDisabled(True) 239 | self.pauseButton.setDisabled(False) 240 | 241 | def stop_batch_work(self): 242 | if self.loadThread: 243 | self.loadThread.pool.terminate() 244 | self.loadThread.pool.join() 245 | logging.critical("手动停止运行!") 246 | self.runButton.setDisabled(False) 247 | self.pauseButton.setDisabled(True) 248 | self.resumeButton.setDisabled(True) 249 | self.stopButton.setDisabled(True) 250 | # if self._loadThread: 251 | # self._loadThread.quit() 252 | # self._loadThread.wait() 253 | # self.imgPathTextBox.setText("AA") 254 | 255 | def changeStyle(self, styleName): 256 | QApplication.setStyle(QStyleFactory.create(styleName)) 257 | self.changePalette() 258 | 259 | def changePalette(self): 260 | QApplication.setPalette(QApplication.style().standardPalette()) 261 | 262 | def updateProgressBar(self, i): 263 | self.progressBar.setValue(i) 264 | 265 | def updateButtonStatus(self, status): 266 | self.runButton.setDisabled(status) 267 | self.pauseButton.setDisabled(not status) 268 | self.resumeButton.setDisabled(True) 269 | self.stopButton.setDisabled(not status) 270 | if not status: 271 | QMessageBox.information(self, '提示', '成功完成扫描!', QMessageBox.Yes) 272 | 273 | def disableCutPathStatus(self): 274 | self.cutPathButton.setDisabled(True) 275 | self.cutPathTextBox.setDisabled(True) 276 | 277 | def clickCutRadioButton(self): 278 | self.cutPathButton.setDisabled(False) 279 | self.cutPathTextBox.setDisabled(False) 280 | self.cutPathButton.setText("选择剪切图片文件夹") 281 | 282 | def clickDecodeRadioButton(self): 283 | self.cutPathButton.setDisabled(False) 284 | self.cutPathTextBox.setDisabled(False) 285 | self.cutPathButton.setText("选择保存二维码识别结果文件夹") 286 | 287 | def createBottomLeftGroupBox(self): 288 | self.bottomLeftGroupBox = QGroupBox("包含二维码的图片操作") 289 | 290 | self.radioButton1 = QRadioButton("删除") 291 | self.radioButton2 = QRadioButton("剪切") 292 | self.radioButton3 = QRadioButton("识别") 293 | self.radioButton2.setChecked(True) 294 | 295 | layout = QGridLayout() 296 | layout.addWidget(self.radioButton1,0,0,1,1) 297 | layout.addWidget(self.radioButton2,1,0,1,1) 298 | layout.addWidget(self.radioButton3,0,1,1,1) 299 | #layout.addStretch(1) 300 | self.bottomLeftGroupBox.setLayout(layout) 301 | 302 | def createTopLeftGroupBox(self): 303 | self.topLeftGroupBox = QGroupBox("设置路径") 304 | 305 | self.imgPathButton = QPushButton("选择原始图片文件夹") 306 | self.imgPathButton.setDefault(True) 307 | 308 | self.imgPathTextBox = QDropLineEdit("") 309 | self.cutPathTextBox = QDropLineEdit("") 310 | 311 | self.cutPathButton = QPushButton("选择剪切图片文件夹") 312 | self.cutPathButton.setDefault(True) 313 | 314 | layout = QVBoxLayout() 315 | layout.addWidget(self.imgPathButton) 316 | layout.addWidget(self.imgPathTextBox) 317 | layout.addWidget(self.cutPathButton) 318 | layout.addWidget(self.cutPathTextBox) 319 | 320 | self.topLeftGroupBox.setLayout(layout) 321 | 322 | def createControlGroupBox(self): 323 | self.controlGroupBox = QGroupBox("控制按钮") 324 | layout = QGridLayout() 325 | self.runButton = QPushButton("启动") 326 | self.runButton.setDefault(True) 327 | self.pauseButton = QPushButton("暂停") 328 | self.pauseButton.setDefault(False) 329 | self.pauseButton.setDisabled(True) 330 | self.resumeButton = QPushButton("继续") 331 | self.resumeButton.setDefault(False) 332 | self.resumeButton.setDisabled(True) 333 | self.stopButton = QPushButton("停止") 334 | self.stopButton.setDefault(False) 335 | self.stopButton.setDisabled(True) 336 | layout.addWidget(self.runButton, 0, 0) 337 | layout.addWidget(self.pauseButton, 0, 1) 338 | layout.addWidget(self.resumeButton, 1, 0) 339 | layout.addWidget(self.stopButton, 1, 1) 340 | self.controlGroupBox.setLayout(layout) 341 | 342 | def createRightGroupBox(self, widget): 343 | self.rightGroupBox = QGroupBox("运行日志") 344 | layout = QHBoxLayout() 345 | widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) 346 | widget.setMaximumBlockCount(10000) 347 | widget.setPlainText("作者:zfb\nhttps://github.com/zfb132/QrScan") 348 | layout.addWidget(widget) 349 | #layout.addStretch(0) 350 | self.rightGroupBox.setLayout(layout) 351 | 352 | def createProgressBar(self): 353 | self.progressBar = QProgressBar() 354 | self.progressBar.setRange(0, 100) 355 | self.progressBar.setValue(0) -------------------------------------------------------------------------------- /docs/result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zfb132/QrScan/dfc1e63ea0beaf57930810c73576f83e91cdc607/docs/result.png -------------------------------------------------------------------------------- /file_version_info.txt: -------------------------------------------------------------------------------- 1 | # UTF-8 2 | # 3 | # For more details about fixed file info 'ffi' see: 4 | # http://msdn.microsoft.com/en-us/library/ms646997.aspx 5 | VSVersionInfo( 6 | ffi=FixedFileInfo( 7 | # filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4) 8 | # Set not needed items to zero 0. 9 | filevers=(V_MAJOR, V_MINOR, V_PATCH, 0), 10 | prodvers=(V_MAJOR, V_MINOR, V_PATCH, 0), 11 | # Contains a bitmask that specifies the valid bits 'flags'r 12 | mask=0x3f, 13 | # Contains a bitmask that specifies the Boolean attributes of the file. 14 | flags=0x0, 15 | # The operating system for which this file was designed. 16 | # 0x4 - NT and there is no need to change it. 17 | OS=0x40004, 18 | # The general type of file. 19 | # 0x1 - the file is an application. 20 | fileType=0x1, 21 | # The function of the file. 22 | # 0x0 - the function is not defined for this fileType 23 | subtype=0x0, 24 | # Creation date and time stamp. 25 | date=(0, 0) 26 | ), 27 | kids=[ 28 | StringFileInfo( 29 | [ 30 | StringTable( 31 | '040904B0', 32 | [StringStruct('CompanyName', 'WHU ZFB'), 33 | StringStruct('FileDescription', '二维码检测程序'), 34 | StringStruct('FileVersion', 'V_MAJOR.V_MINOR.V_PATCH.0 (COMMIT_HASH)'), 35 | StringStruct('InternalName', 'QrScan.Exe'), 36 | StringStruct('LegalCopyright', '© https://github.com/zfb132. All rights reserved.'), 37 | StringStruct('OriginalFilename', 'QrScan_COMMIT_HASH_YYYYMMDDHHMM'), 38 | StringStruct('ProductName', '二维码检测程序'), 39 | StringStruct('ProductVersion', 'V_MAJOR.V_MINOR.V_PATCH.0')]) 40 | ]), 41 | VarFileInfo([VarStruct('Translation', [2052, 1200])]) 42 | ] 43 | ) -------------------------------------------------------------------------------- /models/detect.caffemodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zfb132/QrScan/dfc1e63ea0beaf57930810c73576f83e91cdc607/models/detect.caffemodel -------------------------------------------------------------------------------- /models/detect.prototxt: -------------------------------------------------------------------------------- 1 | layer { 2 | name: "data" 3 | type: "Input" 4 | top: "data" 5 | input_param { 6 | shape { 7 | dim: 1 8 | dim: 1 9 | dim: 384 10 | dim: 384 11 | } 12 | } 13 | } 14 | layer { 15 | name: "data/bn" 16 | type: "BatchNorm" 17 | bottom: "data" 18 | top: "data" 19 | param { 20 | lr_mult: 0.0 21 | decay_mult: 0.0 22 | } 23 | param { 24 | lr_mult: 0.0 25 | decay_mult: 0.0 26 | } 27 | param { 28 | lr_mult: 0.0 29 | decay_mult: 0.0 30 | } 31 | } 32 | layer { 33 | name: "data/bn/scale" 34 | type: "Scale" 35 | bottom: "data" 36 | top: "data" 37 | param { 38 | lr_mult: 1.0 39 | decay_mult: 0.0 40 | } 41 | param { 42 | lr_mult: 1.0 43 | decay_mult: 0.0 44 | } 45 | scale_param { 46 | filler { 47 | type: "constant" 48 | value: 1.0 49 | } 50 | bias_term: true 51 | bias_filler { 52 | type: "constant" 53 | value: 0.0 54 | } 55 | } 56 | } 57 | layer { 58 | name: "stage1" 59 | type: "Convolution" 60 | bottom: "data" 61 | top: "stage1" 62 | param { 63 | lr_mult: 1.0 64 | decay_mult: 1.0 65 | } 66 | param { 67 | lr_mult: 1.0 68 | decay_mult: 0.0 69 | } 70 | convolution_param { 71 | num_output: 24 72 | bias_term: true 73 | pad: 1 74 | kernel_size: 3 75 | group: 1 76 | stride: 2 77 | weight_filler { 78 | type: "msra" 79 | } 80 | dilation: 1 81 | } 82 | } 83 | layer { 84 | name: "stage1/bn" 85 | type: "BatchNorm" 86 | bottom: "stage1" 87 | top: "stage1" 88 | param { 89 | lr_mult: 0.0 90 | decay_mult: 0.0 91 | } 92 | param { 93 | lr_mult: 0.0 94 | decay_mult: 0.0 95 | } 96 | param { 97 | lr_mult: 0.0 98 | decay_mult: 0.0 99 | } 100 | } 101 | layer { 102 | name: "stage1/bn/scale" 103 | type: "Scale" 104 | bottom: "stage1" 105 | top: "stage1" 106 | param { 107 | lr_mult: 1.0 108 | decay_mult: 0.0 109 | } 110 | param { 111 | lr_mult: 1.0 112 | decay_mult: 0.0 113 | } 114 | scale_param { 115 | filler { 116 | type: "constant" 117 | value: 1.0 118 | } 119 | bias_term: true 120 | bias_filler { 121 | type: "constant" 122 | value: 0.0 123 | } 124 | } 125 | } 126 | layer { 127 | name: "stage1/relu" 128 | type: "ReLU" 129 | bottom: "stage1" 130 | top: "stage1" 131 | } 132 | layer { 133 | name: "stage2" 134 | type: "Pooling" 135 | bottom: "stage1" 136 | top: "stage2" 137 | pooling_param { 138 | pool: MAX 139 | kernel_size: 3 140 | stride: 2 141 | pad: 0 142 | } 143 | } 144 | layer { 145 | name: "stage3_1/conv1" 146 | type: "Convolution" 147 | bottom: "stage2" 148 | top: "stage3_1/conv1" 149 | param { 150 | lr_mult: 1.0 151 | decay_mult: 1.0 152 | } 153 | convolution_param { 154 | num_output: 16 155 | pad: 0 156 | kernel_size: 1 157 | group: 1 158 | stride: 1 159 | weight_filler { 160 | type: "msra" 161 | } 162 | dilation: 1 163 | } 164 | } 165 | layer { 166 | name: "stage3_1/conv1/relu" 167 | type: "ReLU" 168 | bottom: "stage3_1/conv1" 169 | top: "stage3_1/conv1" 170 | } 171 | layer { 172 | name: "stage3_1/conv2" 173 | type: "Convolution" 174 | bottom: "stage3_1/conv1" 175 | top: "stage3_1/conv2" 176 | param { 177 | lr_mult: 1.0 178 | decay_mult: 1.0 179 | } 180 | convolution_param { 181 | num_output: 16 182 | pad: 1 183 | kernel_size: 3 184 | group: 16 185 | stride: 2 186 | weight_filler { 187 | type: "msra" 188 | } 189 | dilation: 1 190 | } 191 | } 192 | layer { 193 | name: "stage3_1/conv3" 194 | type: "Convolution" 195 | bottom: "stage3_1/conv2" 196 | top: "stage3_1/conv3" 197 | param { 198 | lr_mult: 1.0 199 | decay_mult: 1.0 200 | } 201 | convolution_param { 202 | num_output: 64 203 | pad: 0 204 | kernel_size: 1 205 | group: 1 206 | stride: 1 207 | weight_filler { 208 | type: "msra" 209 | } 210 | dilation: 1 211 | } 212 | } 213 | layer { 214 | name: "stage3_1/relu" 215 | type: "ReLU" 216 | bottom: "stage3_1/conv3" 217 | top: "stage3_1/conv3" 218 | } 219 | layer { 220 | name: "stage3_2/conv1" 221 | type: "Convolution" 222 | bottom: "stage3_1/conv3" 223 | top: "stage3_2/conv1" 224 | param { 225 | lr_mult: 1.0 226 | decay_mult: 1.0 227 | } 228 | convolution_param { 229 | num_output: 16 230 | pad: 0 231 | kernel_size: 1 232 | group: 1 233 | stride: 1 234 | weight_filler { 235 | type: "msra" 236 | } 237 | dilation: 1 238 | } 239 | } 240 | layer { 241 | name: "stage3_2/conv1/relu" 242 | type: "ReLU" 243 | bottom: "stage3_2/conv1" 244 | top: "stage3_2/conv1" 245 | } 246 | layer { 247 | name: "stage3_2/conv2" 248 | type: "Convolution" 249 | bottom: "stage3_2/conv1" 250 | top: "stage3_2/conv2" 251 | param { 252 | lr_mult: 1.0 253 | decay_mult: 1.0 254 | } 255 | convolution_param { 256 | num_output: 16 257 | pad: 1 258 | kernel_size: 3 259 | group: 16 260 | stride: 1 261 | weight_filler { 262 | type: "msra" 263 | } 264 | dilation: 1 265 | } 266 | } 267 | layer { 268 | name: "stage3_2/conv3" 269 | type: "Convolution" 270 | bottom: "stage3_2/conv2" 271 | top: "stage3_2/conv3" 272 | param { 273 | lr_mult: 1.0 274 | decay_mult: 1.0 275 | } 276 | convolution_param { 277 | num_output: 64 278 | pad: 0 279 | kernel_size: 1 280 | group: 1 281 | stride: 1 282 | weight_filler { 283 | type: "msra" 284 | } 285 | dilation: 1 286 | } 287 | } 288 | layer { 289 | name: "stage3_2/sum" 290 | type: "Eltwise" 291 | bottom: "stage3_1/conv3" 292 | bottom: "stage3_2/conv3" 293 | top: "stage3_2/sum" 294 | eltwise_param { 295 | operation: SUM 296 | } 297 | } 298 | layer { 299 | name: "stage3_2/relu" 300 | type: "ReLU" 301 | bottom: "stage3_2/sum" 302 | top: "stage3_2/sum" 303 | } 304 | layer { 305 | name: "stage3_3/conv1" 306 | type: "Convolution" 307 | bottom: "stage3_2/sum" 308 | top: "stage3_3/conv1" 309 | param { 310 | lr_mult: 1.0 311 | decay_mult: 1.0 312 | } 313 | convolution_param { 314 | num_output: 16 315 | pad: 0 316 | kernel_size: 1 317 | group: 1 318 | stride: 1 319 | weight_filler { 320 | type: "msra" 321 | } 322 | dilation: 1 323 | } 324 | } 325 | layer { 326 | name: "stage3_3/conv1/relu" 327 | type: "ReLU" 328 | bottom: "stage3_3/conv1" 329 | top: "stage3_3/conv1" 330 | } 331 | layer { 332 | name: "stage3_3/conv2" 333 | type: "Convolution" 334 | bottom: "stage3_3/conv1" 335 | top: "stage3_3/conv2" 336 | param { 337 | lr_mult: 1.0 338 | decay_mult: 1.0 339 | } 340 | convolution_param { 341 | num_output: 16 342 | pad: 1 343 | kernel_size: 3 344 | group: 16 345 | stride: 1 346 | weight_filler { 347 | type: "msra" 348 | } 349 | dilation: 1 350 | } 351 | } 352 | layer { 353 | name: "stage3_3/conv3" 354 | type: "Convolution" 355 | bottom: "stage3_3/conv2" 356 | top: "stage3_3/conv3" 357 | param { 358 | lr_mult: 1.0 359 | decay_mult: 1.0 360 | } 361 | convolution_param { 362 | num_output: 64 363 | pad: 0 364 | kernel_size: 1 365 | group: 1 366 | stride: 1 367 | weight_filler { 368 | type: "msra" 369 | } 370 | dilation: 1 371 | } 372 | } 373 | layer { 374 | name: "stage3_3/sum" 375 | type: "Eltwise" 376 | bottom: "stage3_2/sum" 377 | bottom: "stage3_3/conv3" 378 | top: "stage3_3/sum" 379 | eltwise_param { 380 | operation: SUM 381 | } 382 | } 383 | layer { 384 | name: "stage3_3/relu" 385 | type: "ReLU" 386 | bottom: "stage3_3/sum" 387 | top: "stage3_3/sum" 388 | } 389 | layer { 390 | name: "stage3_4/conv1" 391 | type: "Convolution" 392 | bottom: "stage3_3/sum" 393 | top: "stage3_4/conv1" 394 | param { 395 | lr_mult: 1.0 396 | decay_mult: 1.0 397 | } 398 | convolution_param { 399 | num_output: 16 400 | pad: 0 401 | kernel_size: 1 402 | group: 1 403 | stride: 1 404 | weight_filler { 405 | type: "msra" 406 | } 407 | dilation: 1 408 | } 409 | } 410 | layer { 411 | name: "stage3_4/conv1/relu" 412 | type: "ReLU" 413 | bottom: "stage3_4/conv1" 414 | top: "stage3_4/conv1" 415 | } 416 | layer { 417 | name: "stage3_4/conv2" 418 | type: "Convolution" 419 | bottom: "stage3_4/conv1" 420 | top: "stage3_4/conv2" 421 | param { 422 | lr_mult: 1.0 423 | decay_mult: 1.0 424 | } 425 | convolution_param { 426 | num_output: 16 427 | pad: 1 428 | kernel_size: 3 429 | group: 16 430 | stride: 1 431 | weight_filler { 432 | type: "msra" 433 | } 434 | dilation: 1 435 | } 436 | } 437 | layer { 438 | name: "stage3_4/conv3" 439 | type: "Convolution" 440 | bottom: "stage3_4/conv2" 441 | top: "stage3_4/conv3" 442 | param { 443 | lr_mult: 1.0 444 | decay_mult: 1.0 445 | } 446 | convolution_param { 447 | num_output: 64 448 | pad: 0 449 | kernel_size: 1 450 | group: 1 451 | stride: 1 452 | weight_filler { 453 | type: "msra" 454 | } 455 | dilation: 1 456 | } 457 | } 458 | layer { 459 | name: "stage3_4/sum" 460 | type: "Eltwise" 461 | bottom: "stage3_3/sum" 462 | bottom: "stage3_4/conv3" 463 | top: "stage3_4/sum" 464 | eltwise_param { 465 | operation: SUM 466 | } 467 | } 468 | layer { 469 | name: "stage3_4/relu" 470 | type: "ReLU" 471 | bottom: "stage3_4/sum" 472 | top: "stage3_4/sum" 473 | } 474 | layer { 475 | name: "stage4_1/conv1" 476 | type: "Convolution" 477 | bottom: "stage3_4/sum" 478 | top: "stage4_1/conv1" 479 | param { 480 | lr_mult: 1.0 481 | decay_mult: 1.0 482 | } 483 | convolution_param { 484 | num_output: 32 485 | pad: 0 486 | kernel_size: 1 487 | group: 1 488 | stride: 1 489 | weight_filler { 490 | type: "msra" 491 | } 492 | dilation: 1 493 | } 494 | } 495 | layer { 496 | name: "stage4_1/conv1/relu" 497 | type: "ReLU" 498 | bottom: "stage4_1/conv1" 499 | top: "stage4_1/conv1" 500 | } 501 | layer { 502 | name: "stage4_1/conv2" 503 | type: "Convolution" 504 | bottom: "stage4_1/conv1" 505 | top: "stage4_1/conv2" 506 | param { 507 | lr_mult: 1.0 508 | decay_mult: 1.0 509 | } 510 | convolution_param { 511 | num_output: 32 512 | pad: 1 513 | kernel_size: 3 514 | group: 32 515 | stride: 2 516 | weight_filler { 517 | type: "msra" 518 | } 519 | dilation: 1 520 | } 521 | } 522 | layer { 523 | name: "stage4_1/conv3" 524 | type: "Convolution" 525 | bottom: "stage4_1/conv2" 526 | top: "stage4_1/conv3" 527 | param { 528 | lr_mult: 1.0 529 | decay_mult: 1.0 530 | } 531 | convolution_param { 532 | num_output: 128 533 | pad: 0 534 | kernel_size: 1 535 | group: 1 536 | stride: 1 537 | weight_filler { 538 | type: "msra" 539 | } 540 | dilation: 1 541 | } 542 | } 543 | layer { 544 | name: "stage4_1/relu" 545 | type: "ReLU" 546 | bottom: "stage4_1/conv3" 547 | top: "stage4_1/conv3" 548 | } 549 | layer { 550 | name: "stage4_2/conv1" 551 | type: "Convolution" 552 | bottom: "stage4_1/conv3" 553 | top: "stage4_2/conv1" 554 | param { 555 | lr_mult: 1.0 556 | decay_mult: 1.0 557 | } 558 | convolution_param { 559 | num_output: 32 560 | pad: 0 561 | kernel_size: 1 562 | group: 1 563 | stride: 1 564 | weight_filler { 565 | type: "msra" 566 | } 567 | dilation: 1 568 | } 569 | } 570 | layer { 571 | name: "stage4_2/conv1/relu" 572 | type: "ReLU" 573 | bottom: "stage4_2/conv1" 574 | top: "stage4_2/conv1" 575 | } 576 | layer { 577 | name: "stage4_2/conv2" 578 | type: "Convolution" 579 | bottom: "stage4_2/conv1" 580 | top: "stage4_2/conv2" 581 | param { 582 | lr_mult: 1.0 583 | decay_mult: 1.0 584 | } 585 | convolution_param { 586 | num_output: 32 587 | pad: 1 588 | kernel_size: 3 589 | group: 32 590 | stride: 1 591 | weight_filler { 592 | type: "msra" 593 | } 594 | dilation: 1 595 | } 596 | } 597 | layer { 598 | name: "stage4_2/conv3" 599 | type: "Convolution" 600 | bottom: "stage4_2/conv2" 601 | top: "stage4_2/conv3" 602 | param { 603 | lr_mult: 1.0 604 | decay_mult: 1.0 605 | } 606 | convolution_param { 607 | num_output: 128 608 | pad: 0 609 | kernel_size: 1 610 | group: 1 611 | stride: 1 612 | weight_filler { 613 | type: "msra" 614 | } 615 | dilation: 1 616 | } 617 | } 618 | layer { 619 | name: "stage4_2/sum" 620 | type: "Eltwise" 621 | bottom: "stage4_1/conv3" 622 | bottom: "stage4_2/conv3" 623 | top: "stage4_2/sum" 624 | eltwise_param { 625 | operation: SUM 626 | } 627 | } 628 | layer { 629 | name: "stage4_2/relu" 630 | type: "ReLU" 631 | bottom: "stage4_2/sum" 632 | top: "stage4_2/sum" 633 | } 634 | layer { 635 | name: "stage4_3/conv1" 636 | type: "Convolution" 637 | bottom: "stage4_2/sum" 638 | top: "stage4_3/conv1" 639 | param { 640 | lr_mult: 1.0 641 | decay_mult: 1.0 642 | } 643 | convolution_param { 644 | num_output: 32 645 | pad: 0 646 | kernel_size: 1 647 | group: 1 648 | stride: 1 649 | weight_filler { 650 | type: "msra" 651 | } 652 | dilation: 1 653 | } 654 | } 655 | layer { 656 | name: "stage4_3/conv1/relu" 657 | type: "ReLU" 658 | bottom: "stage4_3/conv1" 659 | top: "stage4_3/conv1" 660 | } 661 | layer { 662 | name: "stage4_3/conv2" 663 | type: "Convolution" 664 | bottom: "stage4_3/conv1" 665 | top: "stage4_3/conv2" 666 | param { 667 | lr_mult: 1.0 668 | decay_mult: 1.0 669 | } 670 | convolution_param { 671 | num_output: 32 672 | pad: 1 673 | kernel_size: 3 674 | group: 32 675 | stride: 1 676 | weight_filler { 677 | type: "msra" 678 | } 679 | dilation: 1 680 | } 681 | } 682 | layer { 683 | name: "stage4_3/conv3" 684 | type: "Convolution" 685 | bottom: "stage4_3/conv2" 686 | top: "stage4_3/conv3" 687 | param { 688 | lr_mult: 1.0 689 | decay_mult: 1.0 690 | } 691 | convolution_param { 692 | num_output: 128 693 | pad: 0 694 | kernel_size: 1 695 | group: 1 696 | stride: 1 697 | weight_filler { 698 | type: "msra" 699 | } 700 | dilation: 1 701 | } 702 | } 703 | layer { 704 | name: "stage4_3/sum" 705 | type: "Eltwise" 706 | bottom: "stage4_2/sum" 707 | bottom: "stage4_3/conv3" 708 | top: "stage4_3/sum" 709 | eltwise_param { 710 | operation: SUM 711 | } 712 | } 713 | layer { 714 | name: "stage4_3/relu" 715 | type: "ReLU" 716 | bottom: "stage4_3/sum" 717 | top: "stage4_3/sum" 718 | } 719 | layer { 720 | name: "stage4_4/conv1" 721 | type: "Convolution" 722 | bottom: "stage4_3/sum" 723 | top: "stage4_4/conv1" 724 | param { 725 | lr_mult: 1.0 726 | decay_mult: 1.0 727 | } 728 | convolution_param { 729 | num_output: 32 730 | pad: 0 731 | kernel_size: 1 732 | group: 1 733 | stride: 1 734 | weight_filler { 735 | type: "msra" 736 | } 737 | dilation: 1 738 | } 739 | } 740 | layer { 741 | name: "stage4_4/conv1/relu" 742 | type: "ReLU" 743 | bottom: "stage4_4/conv1" 744 | top: "stage4_4/conv1" 745 | } 746 | layer { 747 | name: "stage4_4/conv2" 748 | type: "Convolution" 749 | bottom: "stage4_4/conv1" 750 | top: "stage4_4/conv2" 751 | param { 752 | lr_mult: 1.0 753 | decay_mult: 1.0 754 | } 755 | convolution_param { 756 | num_output: 32 757 | pad: 1 758 | kernel_size: 3 759 | group: 32 760 | stride: 1 761 | weight_filler { 762 | type: "msra" 763 | } 764 | dilation: 1 765 | } 766 | } 767 | layer { 768 | name: "stage4_4/conv3" 769 | type: "Convolution" 770 | bottom: "stage4_4/conv2" 771 | top: "stage4_4/conv3" 772 | param { 773 | lr_mult: 1.0 774 | decay_mult: 1.0 775 | } 776 | convolution_param { 777 | num_output: 128 778 | pad: 0 779 | kernel_size: 1 780 | group: 1 781 | stride: 1 782 | weight_filler { 783 | type: "msra" 784 | } 785 | dilation: 1 786 | } 787 | } 788 | layer { 789 | name: "stage4_4/sum" 790 | type: "Eltwise" 791 | bottom: "stage4_3/sum" 792 | bottom: "stage4_4/conv3" 793 | top: "stage4_4/sum" 794 | eltwise_param { 795 | operation: SUM 796 | } 797 | } 798 | layer { 799 | name: "stage4_4/relu" 800 | type: "ReLU" 801 | bottom: "stage4_4/sum" 802 | top: "stage4_4/sum" 803 | } 804 | layer { 805 | name: "stage4_5/conv1" 806 | type: "Convolution" 807 | bottom: "stage4_4/sum" 808 | top: "stage4_5/conv1" 809 | param { 810 | lr_mult: 1.0 811 | decay_mult: 1.0 812 | } 813 | convolution_param { 814 | num_output: 32 815 | pad: 0 816 | kernel_size: 1 817 | group: 1 818 | stride: 1 819 | weight_filler { 820 | type: "msra" 821 | } 822 | dilation: 1 823 | } 824 | } 825 | layer { 826 | name: "stage4_5/conv1/relu" 827 | type: "ReLU" 828 | bottom: "stage4_5/conv1" 829 | top: "stage4_5/conv1" 830 | } 831 | layer { 832 | name: "stage4_5/conv2" 833 | type: "Convolution" 834 | bottom: "stage4_5/conv1" 835 | top: "stage4_5/conv2" 836 | param { 837 | lr_mult: 1.0 838 | decay_mult: 1.0 839 | } 840 | convolution_param { 841 | num_output: 32 842 | pad: 1 843 | kernel_size: 3 844 | group: 32 845 | stride: 1 846 | weight_filler { 847 | type: "msra" 848 | } 849 | dilation: 1 850 | } 851 | } 852 | layer { 853 | name: "stage4_5/conv3" 854 | type: "Convolution" 855 | bottom: "stage4_5/conv2" 856 | top: "stage4_5/conv3" 857 | param { 858 | lr_mult: 1.0 859 | decay_mult: 1.0 860 | } 861 | convolution_param { 862 | num_output: 128 863 | pad: 0 864 | kernel_size: 1 865 | group: 1 866 | stride: 1 867 | weight_filler { 868 | type: "msra" 869 | } 870 | dilation: 1 871 | } 872 | } 873 | layer { 874 | name: "stage4_5/sum" 875 | type: "Eltwise" 876 | bottom: "stage4_4/sum" 877 | bottom: "stage4_5/conv3" 878 | top: "stage4_5/sum" 879 | eltwise_param { 880 | operation: SUM 881 | } 882 | } 883 | layer { 884 | name: "stage4_5/relu" 885 | type: "ReLU" 886 | bottom: "stage4_5/sum" 887 | top: "stage4_5/sum" 888 | } 889 | layer { 890 | name: "stage4_6/conv1" 891 | type: "Convolution" 892 | bottom: "stage4_5/sum" 893 | top: "stage4_6/conv1" 894 | param { 895 | lr_mult: 1.0 896 | decay_mult: 1.0 897 | } 898 | convolution_param { 899 | num_output: 32 900 | pad: 0 901 | kernel_size: 1 902 | group: 1 903 | stride: 1 904 | weight_filler { 905 | type: "msra" 906 | } 907 | dilation: 1 908 | } 909 | } 910 | layer { 911 | name: "stage4_6/conv1/relu" 912 | type: "ReLU" 913 | bottom: "stage4_6/conv1" 914 | top: "stage4_6/conv1" 915 | } 916 | layer { 917 | name: "stage4_6/conv2" 918 | type: "Convolution" 919 | bottom: "stage4_6/conv1" 920 | top: "stage4_6/conv2" 921 | param { 922 | lr_mult: 1.0 923 | decay_mult: 1.0 924 | } 925 | convolution_param { 926 | num_output: 32 927 | pad: 1 928 | kernel_size: 3 929 | group: 32 930 | stride: 1 931 | weight_filler { 932 | type: "msra" 933 | } 934 | dilation: 1 935 | } 936 | } 937 | layer { 938 | name: "stage4_6/conv3" 939 | type: "Convolution" 940 | bottom: "stage4_6/conv2" 941 | top: "stage4_6/conv3" 942 | param { 943 | lr_mult: 1.0 944 | decay_mult: 1.0 945 | } 946 | convolution_param { 947 | num_output: 128 948 | pad: 0 949 | kernel_size: 1 950 | group: 1 951 | stride: 1 952 | weight_filler { 953 | type: "msra" 954 | } 955 | dilation: 1 956 | } 957 | } 958 | layer { 959 | name: "stage4_6/sum" 960 | type: "Eltwise" 961 | bottom: "stage4_5/sum" 962 | bottom: "stage4_6/conv3" 963 | top: "stage4_6/sum" 964 | eltwise_param { 965 | operation: SUM 966 | } 967 | } 968 | layer { 969 | name: "stage4_6/relu" 970 | type: "ReLU" 971 | bottom: "stage4_6/sum" 972 | top: "stage4_6/sum" 973 | } 974 | layer { 975 | name: "stage4_7/conv1" 976 | type: "Convolution" 977 | bottom: "stage4_6/sum" 978 | top: "stage4_7/conv1" 979 | param { 980 | lr_mult: 1.0 981 | decay_mult: 1.0 982 | } 983 | convolution_param { 984 | num_output: 32 985 | pad: 0 986 | kernel_size: 1 987 | group: 1 988 | stride: 1 989 | weight_filler { 990 | type: "msra" 991 | } 992 | dilation: 1 993 | } 994 | } 995 | layer { 996 | name: "stage4_7/conv1/relu" 997 | type: "ReLU" 998 | bottom: "stage4_7/conv1" 999 | top: "stage4_7/conv1" 1000 | } 1001 | layer { 1002 | name: "stage4_7/conv2" 1003 | type: "Convolution" 1004 | bottom: "stage4_7/conv1" 1005 | top: "stage4_7/conv2" 1006 | param { 1007 | lr_mult: 1.0 1008 | decay_mult: 1.0 1009 | } 1010 | convolution_param { 1011 | num_output: 32 1012 | pad: 1 1013 | kernel_size: 3 1014 | group: 32 1015 | stride: 1 1016 | weight_filler { 1017 | type: "msra" 1018 | } 1019 | dilation: 1 1020 | } 1021 | } 1022 | layer { 1023 | name: "stage4_7/conv3" 1024 | type: "Convolution" 1025 | bottom: "stage4_7/conv2" 1026 | top: "stage4_7/conv3" 1027 | param { 1028 | lr_mult: 1.0 1029 | decay_mult: 1.0 1030 | } 1031 | convolution_param { 1032 | num_output: 128 1033 | pad: 0 1034 | kernel_size: 1 1035 | group: 1 1036 | stride: 1 1037 | weight_filler { 1038 | type: "msra" 1039 | } 1040 | dilation: 1 1041 | } 1042 | } 1043 | layer { 1044 | name: "stage4_7/sum" 1045 | type: "Eltwise" 1046 | bottom: "stage4_6/sum" 1047 | bottom: "stage4_7/conv3" 1048 | top: "stage4_7/sum" 1049 | eltwise_param { 1050 | operation: SUM 1051 | } 1052 | } 1053 | layer { 1054 | name: "stage4_7/relu" 1055 | type: "ReLU" 1056 | bottom: "stage4_7/sum" 1057 | top: "stage4_7/sum" 1058 | } 1059 | layer { 1060 | name: "stage4_8/conv1" 1061 | type: "Convolution" 1062 | bottom: "stage4_7/sum" 1063 | top: "stage4_8/conv1" 1064 | param { 1065 | lr_mult: 1.0 1066 | decay_mult: 1.0 1067 | } 1068 | convolution_param { 1069 | num_output: 32 1070 | pad: 0 1071 | kernel_size: 1 1072 | group: 1 1073 | stride: 1 1074 | weight_filler { 1075 | type: "msra" 1076 | } 1077 | dilation: 1 1078 | } 1079 | } 1080 | layer { 1081 | name: "stage4_8/conv1/relu" 1082 | type: "ReLU" 1083 | bottom: "stage4_8/conv1" 1084 | top: "stage4_8/conv1" 1085 | } 1086 | layer { 1087 | name: "stage4_8/conv2" 1088 | type: "Convolution" 1089 | bottom: "stage4_8/conv1" 1090 | top: "stage4_8/conv2" 1091 | param { 1092 | lr_mult: 1.0 1093 | decay_mult: 1.0 1094 | } 1095 | convolution_param { 1096 | num_output: 32 1097 | pad: 1 1098 | kernel_size: 3 1099 | group: 32 1100 | stride: 1 1101 | weight_filler { 1102 | type: "msra" 1103 | } 1104 | dilation: 1 1105 | } 1106 | } 1107 | layer { 1108 | name: "stage4_8/conv3" 1109 | type: "Convolution" 1110 | bottom: "stage4_8/conv2" 1111 | top: "stage4_8/conv3" 1112 | param { 1113 | lr_mult: 1.0 1114 | decay_mult: 1.0 1115 | } 1116 | convolution_param { 1117 | num_output: 128 1118 | pad: 0 1119 | kernel_size: 1 1120 | group: 1 1121 | stride: 1 1122 | weight_filler { 1123 | type: "msra" 1124 | } 1125 | dilation: 1 1126 | } 1127 | } 1128 | layer { 1129 | name: "stage4_8/sum" 1130 | type: "Eltwise" 1131 | bottom: "stage4_7/sum" 1132 | bottom: "stage4_8/conv3" 1133 | top: "stage4_8/sum" 1134 | eltwise_param { 1135 | operation: SUM 1136 | } 1137 | } 1138 | layer { 1139 | name: "stage4_8/relu" 1140 | type: "ReLU" 1141 | bottom: "stage4_8/sum" 1142 | top: "stage4_8/sum" 1143 | } 1144 | layer { 1145 | name: "stage5_1/conv1" 1146 | type: "Convolution" 1147 | bottom: "stage4_8/sum" 1148 | top: "stage5_1/conv1" 1149 | param { 1150 | lr_mult: 1.0 1151 | decay_mult: 1.0 1152 | } 1153 | convolution_param { 1154 | num_output: 32 1155 | pad: 0 1156 | kernel_size: 1 1157 | group: 1 1158 | stride: 1 1159 | weight_filler { 1160 | type: "msra" 1161 | } 1162 | dilation: 1 1163 | } 1164 | } 1165 | layer { 1166 | name: "stage5_1/conv1/relu" 1167 | type: "ReLU" 1168 | bottom: "stage5_1/conv1" 1169 | top: "stage5_1/conv1" 1170 | } 1171 | layer { 1172 | name: "stage5_1/conv2" 1173 | type: "Convolution" 1174 | bottom: "stage5_1/conv1" 1175 | top: "stage5_1/conv2" 1176 | param { 1177 | lr_mult: 1.0 1178 | decay_mult: 1.0 1179 | } 1180 | convolution_param { 1181 | num_output: 32 1182 | pad: 2 1183 | kernel_size: 3 1184 | group: 32 1185 | stride: 2 1186 | weight_filler { 1187 | type: "msra" 1188 | } 1189 | dilation: 2 1190 | } 1191 | } 1192 | layer { 1193 | name: "stage5_1/conv3" 1194 | type: "Convolution" 1195 | bottom: "stage5_1/conv2" 1196 | top: "stage5_1/conv3" 1197 | param { 1198 | lr_mult: 1.0 1199 | decay_mult: 1.0 1200 | } 1201 | convolution_param { 1202 | num_output: 128 1203 | pad: 0 1204 | kernel_size: 1 1205 | group: 1 1206 | stride: 1 1207 | weight_filler { 1208 | type: "msra" 1209 | } 1210 | dilation: 1 1211 | } 1212 | } 1213 | layer { 1214 | name: "stage5_1/relu" 1215 | type: "ReLU" 1216 | bottom: "stage5_1/conv3" 1217 | top: "stage5_1/conv3" 1218 | } 1219 | layer { 1220 | name: "stage5_2/conv1" 1221 | type: "Convolution" 1222 | bottom: "stage5_1/conv3" 1223 | top: "stage5_2/conv1" 1224 | param { 1225 | lr_mult: 1.0 1226 | decay_mult: 1.0 1227 | } 1228 | convolution_param { 1229 | num_output: 32 1230 | pad: 0 1231 | kernel_size: 1 1232 | group: 1 1233 | stride: 1 1234 | weight_filler { 1235 | type: "msra" 1236 | } 1237 | dilation: 1 1238 | } 1239 | } 1240 | layer { 1241 | name: "stage5_2/conv1/relu" 1242 | type: "ReLU" 1243 | bottom: "stage5_2/conv1" 1244 | top: "stage5_2/conv1" 1245 | } 1246 | layer { 1247 | name: "stage5_2/conv2" 1248 | type: "Convolution" 1249 | bottom: "stage5_2/conv1" 1250 | top: "stage5_2/conv2" 1251 | param { 1252 | lr_mult: 1.0 1253 | decay_mult: 1.0 1254 | } 1255 | convolution_param { 1256 | num_output: 32 1257 | pad: 2 1258 | kernel_size: 3 1259 | group: 32 1260 | stride: 1 1261 | weight_filler { 1262 | type: "msra" 1263 | } 1264 | dilation: 2 1265 | } 1266 | } 1267 | layer { 1268 | name: "stage5_2/conv3" 1269 | type: "Convolution" 1270 | bottom: "stage5_2/conv2" 1271 | top: "stage5_2/conv3" 1272 | param { 1273 | lr_mult: 1.0 1274 | decay_mult: 1.0 1275 | } 1276 | convolution_param { 1277 | num_output: 128 1278 | pad: 0 1279 | kernel_size: 1 1280 | group: 1 1281 | stride: 1 1282 | weight_filler { 1283 | type: "msra" 1284 | } 1285 | dilation: 1 1286 | } 1287 | } 1288 | layer { 1289 | name: "stage5_2/sum" 1290 | type: "Eltwise" 1291 | bottom: "stage5_1/conv3" 1292 | bottom: "stage5_2/conv3" 1293 | top: "stage5_2/sum" 1294 | eltwise_param { 1295 | operation: SUM 1296 | } 1297 | } 1298 | layer { 1299 | name: "stage5_2/relu" 1300 | type: "ReLU" 1301 | bottom: "stage5_2/sum" 1302 | top: "stage5_2/sum" 1303 | } 1304 | layer { 1305 | name: "stage5_3/conv1" 1306 | type: "Convolution" 1307 | bottom: "stage5_2/sum" 1308 | top: "stage5_3/conv1" 1309 | param { 1310 | lr_mult: 1.0 1311 | decay_mult: 1.0 1312 | } 1313 | convolution_param { 1314 | num_output: 32 1315 | pad: 0 1316 | kernel_size: 1 1317 | group: 1 1318 | stride: 1 1319 | weight_filler { 1320 | type: "msra" 1321 | } 1322 | dilation: 1 1323 | } 1324 | } 1325 | layer { 1326 | name: "stage5_3/conv1/relu" 1327 | type: "ReLU" 1328 | bottom: "stage5_3/conv1" 1329 | top: "stage5_3/conv1" 1330 | } 1331 | layer { 1332 | name: "stage5_3/conv2" 1333 | type: "Convolution" 1334 | bottom: "stage5_3/conv1" 1335 | top: "stage5_3/conv2" 1336 | param { 1337 | lr_mult: 1.0 1338 | decay_mult: 1.0 1339 | } 1340 | convolution_param { 1341 | num_output: 32 1342 | pad: 2 1343 | kernel_size: 3 1344 | group: 32 1345 | stride: 1 1346 | weight_filler { 1347 | type: "msra" 1348 | } 1349 | dilation: 2 1350 | } 1351 | } 1352 | layer { 1353 | name: "stage5_3/conv3" 1354 | type: "Convolution" 1355 | bottom: "stage5_3/conv2" 1356 | top: "stage5_3/conv3" 1357 | param { 1358 | lr_mult: 1.0 1359 | decay_mult: 1.0 1360 | } 1361 | convolution_param { 1362 | num_output: 128 1363 | pad: 0 1364 | kernel_size: 1 1365 | group: 1 1366 | stride: 1 1367 | weight_filler { 1368 | type: "msra" 1369 | } 1370 | dilation: 1 1371 | } 1372 | } 1373 | layer { 1374 | name: "stage5_3/sum" 1375 | type: "Eltwise" 1376 | bottom: "stage5_2/sum" 1377 | bottom: "stage5_3/conv3" 1378 | top: "stage5_3/sum" 1379 | eltwise_param { 1380 | operation: SUM 1381 | } 1382 | } 1383 | layer { 1384 | name: "stage5_3/relu" 1385 | type: "ReLU" 1386 | bottom: "stage5_3/sum" 1387 | top: "stage5_3/sum" 1388 | } 1389 | layer { 1390 | name: "stage5_4/conv1" 1391 | type: "Convolution" 1392 | bottom: "stage5_3/sum" 1393 | top: "stage5_4/conv1" 1394 | param { 1395 | lr_mult: 1.0 1396 | decay_mult: 1.0 1397 | } 1398 | convolution_param { 1399 | num_output: 32 1400 | pad: 0 1401 | kernel_size: 1 1402 | group: 1 1403 | stride: 1 1404 | weight_filler { 1405 | type: "msra" 1406 | } 1407 | dilation: 1 1408 | } 1409 | } 1410 | layer { 1411 | name: "stage5_4/conv1/relu" 1412 | type: "ReLU" 1413 | bottom: "stage5_4/conv1" 1414 | top: "stage5_4/conv1" 1415 | } 1416 | layer { 1417 | name: "stage5_4/conv2" 1418 | type: "Convolution" 1419 | bottom: "stage5_4/conv1" 1420 | top: "stage5_4/conv2" 1421 | param { 1422 | lr_mult: 1.0 1423 | decay_mult: 1.0 1424 | } 1425 | convolution_param { 1426 | num_output: 32 1427 | pad: 2 1428 | kernel_size: 3 1429 | group: 32 1430 | stride: 1 1431 | weight_filler { 1432 | type: "msra" 1433 | } 1434 | dilation: 2 1435 | } 1436 | } 1437 | layer { 1438 | name: "stage5_4/conv3" 1439 | type: "Convolution" 1440 | bottom: "stage5_4/conv2" 1441 | top: "stage5_4/conv3" 1442 | param { 1443 | lr_mult: 1.0 1444 | decay_mult: 1.0 1445 | } 1446 | convolution_param { 1447 | num_output: 128 1448 | pad: 0 1449 | kernel_size: 1 1450 | group: 1 1451 | stride: 1 1452 | weight_filler { 1453 | type: "msra" 1454 | } 1455 | dilation: 1 1456 | } 1457 | } 1458 | layer { 1459 | name: "stage5_4/sum" 1460 | type: "Eltwise" 1461 | bottom: "stage5_3/sum" 1462 | bottom: "stage5_4/conv3" 1463 | top: "stage5_4/sum" 1464 | eltwise_param { 1465 | operation: SUM 1466 | } 1467 | } 1468 | layer { 1469 | name: "stage5_4/relu" 1470 | type: "ReLU" 1471 | bottom: "stage5_4/sum" 1472 | top: "stage5_4/sum" 1473 | } 1474 | layer { 1475 | name: "stage6_1/conv4" 1476 | type: "Convolution" 1477 | bottom: "stage5_4/sum" 1478 | top: "stage6_1/conv4" 1479 | param { 1480 | lr_mult: 1.0 1481 | decay_mult: 1.0 1482 | } 1483 | convolution_param { 1484 | num_output: 128 1485 | pad: 0 1486 | kernel_size: 1 1487 | group: 1 1488 | stride: 1 1489 | weight_filler { 1490 | type: "msra" 1491 | } 1492 | dilation: 1 1493 | } 1494 | } 1495 | layer { 1496 | name: "stage6_1/conv1" 1497 | type: "Convolution" 1498 | bottom: "stage5_4/sum" 1499 | top: "stage6_1/conv1" 1500 | param { 1501 | lr_mult: 1.0 1502 | decay_mult: 1.0 1503 | } 1504 | convolution_param { 1505 | num_output: 32 1506 | pad: 0 1507 | kernel_size: 1 1508 | group: 1 1509 | stride: 1 1510 | weight_filler { 1511 | type: "msra" 1512 | } 1513 | dilation: 1 1514 | } 1515 | } 1516 | layer { 1517 | name: "stage6_1/conv1/relu" 1518 | type: "ReLU" 1519 | bottom: "stage6_1/conv1" 1520 | top: "stage6_1/conv1" 1521 | } 1522 | layer { 1523 | name: "stage6_1/conv2" 1524 | type: "Convolution" 1525 | bottom: "stage6_1/conv1" 1526 | top: "stage6_1/conv2" 1527 | param { 1528 | lr_mult: 1.0 1529 | decay_mult: 1.0 1530 | } 1531 | convolution_param { 1532 | num_output: 32 1533 | pad: 2 1534 | kernel_size: 3 1535 | group: 32 1536 | stride: 1 1537 | weight_filler { 1538 | type: "msra" 1539 | } 1540 | dilation: 2 1541 | } 1542 | } 1543 | layer { 1544 | name: "stage6_1/conv3" 1545 | type: "Convolution" 1546 | bottom: "stage6_1/conv2" 1547 | top: "stage6_1/conv3" 1548 | param { 1549 | lr_mult: 1.0 1550 | decay_mult: 1.0 1551 | } 1552 | convolution_param { 1553 | num_output: 128 1554 | pad: 0 1555 | kernel_size: 1 1556 | group: 1 1557 | stride: 1 1558 | weight_filler { 1559 | type: "msra" 1560 | } 1561 | dilation: 1 1562 | } 1563 | } 1564 | layer { 1565 | name: "stage6_1/sum" 1566 | type: "Eltwise" 1567 | bottom: "stage6_1/conv4" 1568 | bottom: "stage6_1/conv3" 1569 | top: "stage6_1/sum" 1570 | eltwise_param { 1571 | operation: SUM 1572 | } 1573 | } 1574 | layer { 1575 | name: "stage6_1/relu" 1576 | type: "ReLU" 1577 | bottom: "stage6_1/sum" 1578 | top: "stage6_1/sum" 1579 | } 1580 | layer { 1581 | name: "stage6_2/conv1" 1582 | type: "Convolution" 1583 | bottom: "stage6_1/sum" 1584 | top: "stage6_2/conv1" 1585 | param { 1586 | lr_mult: 1.0 1587 | decay_mult: 1.0 1588 | } 1589 | convolution_param { 1590 | num_output: 32 1591 | pad: 0 1592 | kernel_size: 1 1593 | group: 1 1594 | stride: 1 1595 | weight_filler { 1596 | type: "msra" 1597 | } 1598 | dilation: 1 1599 | } 1600 | } 1601 | layer { 1602 | name: "stage6_2/conv1/relu" 1603 | type: "ReLU" 1604 | bottom: "stage6_2/conv1" 1605 | top: "stage6_2/conv1" 1606 | } 1607 | layer { 1608 | name: "stage6_2/conv2" 1609 | type: "Convolution" 1610 | bottom: "stage6_2/conv1" 1611 | top: "stage6_2/conv2" 1612 | param { 1613 | lr_mult: 1.0 1614 | decay_mult: 1.0 1615 | } 1616 | convolution_param { 1617 | num_output: 32 1618 | pad: 2 1619 | kernel_size: 3 1620 | group: 32 1621 | stride: 1 1622 | weight_filler { 1623 | type: "msra" 1624 | } 1625 | dilation: 2 1626 | } 1627 | } 1628 | layer { 1629 | name: "stage6_2/conv3" 1630 | type: "Convolution" 1631 | bottom: "stage6_2/conv2" 1632 | top: "stage6_2/conv3" 1633 | param { 1634 | lr_mult: 1.0 1635 | decay_mult: 1.0 1636 | } 1637 | convolution_param { 1638 | num_output: 128 1639 | pad: 0 1640 | kernel_size: 1 1641 | group: 1 1642 | stride: 1 1643 | weight_filler { 1644 | type: "msra" 1645 | } 1646 | dilation: 1 1647 | } 1648 | } 1649 | layer { 1650 | name: "stage6_2/sum" 1651 | type: "Eltwise" 1652 | bottom: "stage6_1/sum" 1653 | bottom: "stage6_2/conv3" 1654 | top: "stage6_2/sum" 1655 | eltwise_param { 1656 | operation: SUM 1657 | } 1658 | } 1659 | layer { 1660 | name: "stage6_2/relu" 1661 | type: "ReLU" 1662 | bottom: "stage6_2/sum" 1663 | top: "stage6_2/sum" 1664 | } 1665 | layer { 1666 | name: "stage7_1/conv4" 1667 | type: "Convolution" 1668 | bottom: "stage6_2/sum" 1669 | top: "stage7_1/conv4" 1670 | param { 1671 | lr_mult: 1.0 1672 | decay_mult: 1.0 1673 | } 1674 | convolution_param { 1675 | num_output: 128 1676 | pad: 0 1677 | kernel_size: 1 1678 | group: 1 1679 | stride: 1 1680 | weight_filler { 1681 | type: "msra" 1682 | } 1683 | dilation: 1 1684 | } 1685 | } 1686 | layer { 1687 | name: "stage7_1/conv1" 1688 | type: "Convolution" 1689 | bottom: "stage6_2/sum" 1690 | top: "stage7_1/conv1" 1691 | param { 1692 | lr_mult: 1.0 1693 | decay_mult: 1.0 1694 | } 1695 | convolution_param { 1696 | num_output: 32 1697 | pad: 0 1698 | kernel_size: 1 1699 | group: 1 1700 | stride: 1 1701 | weight_filler { 1702 | type: "msra" 1703 | } 1704 | dilation: 1 1705 | } 1706 | } 1707 | layer { 1708 | name: "stage7_1/conv1/relu" 1709 | type: "ReLU" 1710 | bottom: "stage7_1/conv1" 1711 | top: "stage7_1/conv1" 1712 | } 1713 | layer { 1714 | name: "stage7_1/conv2" 1715 | type: "Convolution" 1716 | bottom: "stage7_1/conv1" 1717 | top: "stage7_1/conv2" 1718 | param { 1719 | lr_mult: 1.0 1720 | decay_mult: 1.0 1721 | } 1722 | convolution_param { 1723 | num_output: 32 1724 | pad: 2 1725 | kernel_size: 3 1726 | group: 32 1727 | stride: 1 1728 | weight_filler { 1729 | type: "msra" 1730 | } 1731 | dilation: 2 1732 | } 1733 | } 1734 | layer { 1735 | name: "stage7_1/conv3" 1736 | type: "Convolution" 1737 | bottom: "stage7_1/conv2" 1738 | top: "stage7_1/conv3" 1739 | param { 1740 | lr_mult: 1.0 1741 | decay_mult: 1.0 1742 | } 1743 | convolution_param { 1744 | num_output: 128 1745 | pad: 0 1746 | kernel_size: 1 1747 | group: 1 1748 | stride: 1 1749 | weight_filler { 1750 | type: "msra" 1751 | } 1752 | dilation: 1 1753 | } 1754 | } 1755 | layer { 1756 | name: "stage7_1/sum" 1757 | type: "Eltwise" 1758 | bottom: "stage7_1/conv4" 1759 | bottom: "stage7_1/conv3" 1760 | top: "stage7_1/sum" 1761 | eltwise_param { 1762 | operation: SUM 1763 | } 1764 | } 1765 | layer { 1766 | name: "stage7_1/relu" 1767 | type: "ReLU" 1768 | bottom: "stage7_1/sum" 1769 | top: "stage7_1/sum" 1770 | } 1771 | layer { 1772 | name: "stage7_2/conv1" 1773 | type: "Convolution" 1774 | bottom: "stage7_1/sum" 1775 | top: "stage7_2/conv1" 1776 | param { 1777 | lr_mult: 1.0 1778 | decay_mult: 1.0 1779 | } 1780 | convolution_param { 1781 | num_output: 32 1782 | pad: 0 1783 | kernel_size: 1 1784 | group: 1 1785 | stride: 1 1786 | weight_filler { 1787 | type: "msra" 1788 | } 1789 | dilation: 1 1790 | } 1791 | } 1792 | layer { 1793 | name: "stage7_2/conv1/relu" 1794 | type: "ReLU" 1795 | bottom: "stage7_2/conv1" 1796 | top: "stage7_2/conv1" 1797 | } 1798 | layer { 1799 | name: "stage7_2/conv2" 1800 | type: "Convolution" 1801 | bottom: "stage7_2/conv1" 1802 | top: "stage7_2/conv2" 1803 | param { 1804 | lr_mult: 1.0 1805 | decay_mult: 1.0 1806 | } 1807 | convolution_param { 1808 | num_output: 32 1809 | pad: 2 1810 | kernel_size: 3 1811 | group: 32 1812 | stride: 1 1813 | weight_filler { 1814 | type: "msra" 1815 | } 1816 | dilation: 2 1817 | } 1818 | } 1819 | layer { 1820 | name: "stage7_2/conv3" 1821 | type: "Convolution" 1822 | bottom: "stage7_2/conv2" 1823 | top: "stage7_2/conv3" 1824 | param { 1825 | lr_mult: 1.0 1826 | decay_mult: 1.0 1827 | } 1828 | convolution_param { 1829 | num_output: 128 1830 | pad: 0 1831 | kernel_size: 1 1832 | group: 1 1833 | stride: 1 1834 | weight_filler { 1835 | type: "msra" 1836 | } 1837 | dilation: 1 1838 | } 1839 | } 1840 | layer { 1841 | name: "stage7_2/sum" 1842 | type: "Eltwise" 1843 | bottom: "stage7_1/sum" 1844 | bottom: "stage7_2/conv3" 1845 | top: "stage7_2/sum" 1846 | eltwise_param { 1847 | operation: SUM 1848 | } 1849 | } 1850 | layer { 1851 | name: "stage7_2/relu" 1852 | type: "ReLU" 1853 | bottom: "stage7_2/sum" 1854 | top: "stage7_2/sum" 1855 | } 1856 | layer { 1857 | name: "stage8_1/conv4" 1858 | type: "Convolution" 1859 | bottom: "stage7_2/sum" 1860 | top: "stage8_1/conv4" 1861 | param { 1862 | lr_mult: 1.0 1863 | decay_mult: 1.0 1864 | } 1865 | convolution_param { 1866 | num_output: 128 1867 | pad: 0 1868 | kernel_size: 1 1869 | group: 1 1870 | stride: 1 1871 | weight_filler { 1872 | type: "msra" 1873 | } 1874 | dilation: 1 1875 | } 1876 | } 1877 | layer { 1878 | name: "stage8_1/conv1" 1879 | type: "Convolution" 1880 | bottom: "stage7_2/sum" 1881 | top: "stage8_1/conv1" 1882 | param { 1883 | lr_mult: 1.0 1884 | decay_mult: 1.0 1885 | } 1886 | convolution_param { 1887 | num_output: 32 1888 | pad: 0 1889 | kernel_size: 1 1890 | group: 1 1891 | stride: 1 1892 | weight_filler { 1893 | type: "msra" 1894 | } 1895 | dilation: 1 1896 | } 1897 | } 1898 | layer { 1899 | name: "stage8_1/conv1/relu" 1900 | type: "ReLU" 1901 | bottom: "stage8_1/conv1" 1902 | top: "stage8_1/conv1" 1903 | } 1904 | layer { 1905 | name: "stage8_1/conv2" 1906 | type: "Convolution" 1907 | bottom: "stage8_1/conv1" 1908 | top: "stage8_1/conv2" 1909 | param { 1910 | lr_mult: 1.0 1911 | decay_mult: 1.0 1912 | } 1913 | convolution_param { 1914 | num_output: 32 1915 | pad: 2 1916 | kernel_size: 3 1917 | group: 32 1918 | stride: 1 1919 | weight_filler { 1920 | type: "msra" 1921 | } 1922 | dilation: 2 1923 | } 1924 | } 1925 | layer { 1926 | name: "stage8_1/conv3" 1927 | type: "Convolution" 1928 | bottom: "stage8_1/conv2" 1929 | top: "stage8_1/conv3" 1930 | param { 1931 | lr_mult: 1.0 1932 | decay_mult: 1.0 1933 | } 1934 | convolution_param { 1935 | num_output: 128 1936 | pad: 0 1937 | kernel_size: 1 1938 | group: 1 1939 | stride: 1 1940 | weight_filler { 1941 | type: "msra" 1942 | } 1943 | dilation: 1 1944 | } 1945 | } 1946 | layer { 1947 | name: "stage8_1/sum" 1948 | type: "Eltwise" 1949 | bottom: "stage8_1/conv4" 1950 | bottom: "stage8_1/conv3" 1951 | top: "stage8_1/sum" 1952 | eltwise_param { 1953 | operation: SUM 1954 | } 1955 | } 1956 | layer { 1957 | name: "stage8_1/relu" 1958 | type: "ReLU" 1959 | bottom: "stage8_1/sum" 1960 | top: "stage8_1/sum" 1961 | } 1962 | layer { 1963 | name: "stage8_2/conv1" 1964 | type: "Convolution" 1965 | bottom: "stage8_1/sum" 1966 | top: "stage8_2/conv1" 1967 | param { 1968 | lr_mult: 1.0 1969 | decay_mult: 1.0 1970 | } 1971 | convolution_param { 1972 | num_output: 32 1973 | pad: 0 1974 | kernel_size: 1 1975 | group: 1 1976 | stride: 1 1977 | weight_filler { 1978 | type: "msra" 1979 | } 1980 | dilation: 1 1981 | } 1982 | } 1983 | layer { 1984 | name: "stage8_2/conv1/relu" 1985 | type: "ReLU" 1986 | bottom: "stage8_2/conv1" 1987 | top: "stage8_2/conv1" 1988 | } 1989 | layer { 1990 | name: "stage8_2/conv2" 1991 | type: "Convolution" 1992 | bottom: "stage8_2/conv1" 1993 | top: "stage8_2/conv2" 1994 | param { 1995 | lr_mult: 1.0 1996 | decay_mult: 1.0 1997 | } 1998 | convolution_param { 1999 | num_output: 32 2000 | pad: 2 2001 | kernel_size: 3 2002 | group: 32 2003 | stride: 1 2004 | weight_filler { 2005 | type: "msra" 2006 | } 2007 | dilation: 2 2008 | } 2009 | } 2010 | layer { 2011 | name: "stage8_2/conv3" 2012 | type: "Convolution" 2013 | bottom: "stage8_2/conv2" 2014 | top: "stage8_2/conv3" 2015 | param { 2016 | lr_mult: 1.0 2017 | decay_mult: 1.0 2018 | } 2019 | convolution_param { 2020 | num_output: 128 2021 | pad: 0 2022 | kernel_size: 1 2023 | group: 1 2024 | stride: 1 2025 | weight_filler { 2026 | type: "msra" 2027 | } 2028 | dilation: 1 2029 | } 2030 | } 2031 | layer { 2032 | name: "stage8_2/sum" 2033 | type: "Eltwise" 2034 | bottom: "stage8_1/sum" 2035 | bottom: "stage8_2/conv3" 2036 | top: "stage8_2/sum" 2037 | eltwise_param { 2038 | operation: SUM 2039 | } 2040 | } 2041 | layer { 2042 | name: "stage8_2/relu" 2043 | type: "ReLU" 2044 | bottom: "stage8_2/sum" 2045 | top: "stage8_2/sum" 2046 | } 2047 | layer { 2048 | name: "cls1/conv" 2049 | type: "Convolution" 2050 | bottom: "stage4_8/sum" 2051 | top: "cls1/conv" 2052 | param { 2053 | lr_mult: 1.0 2054 | decay_mult: 1.0 2055 | } 2056 | param { 2057 | lr_mult: 1.0 2058 | decay_mult: 0.0 2059 | } 2060 | convolution_param { 2061 | num_output: 12 2062 | bias_term: true 2063 | pad: 0 2064 | kernel_size: 1 2065 | group: 1 2066 | stride: 1 2067 | weight_filler { 2068 | type: "msra" 2069 | } 2070 | dilation: 1 2071 | } 2072 | } 2073 | layer { 2074 | name: "cls1/permute" 2075 | type: "Permute" 2076 | bottom: "cls1/conv" 2077 | top: "cls1/permute" 2078 | permute_param { 2079 | order: 0 2080 | order: 2 2081 | order: 3 2082 | order: 1 2083 | } 2084 | } 2085 | layer { 2086 | name: "cls1/flatten" 2087 | type: "Flatten" 2088 | bottom: "cls1/permute" 2089 | top: "cls1/flatten" 2090 | flatten_param { 2091 | axis: 1 2092 | } 2093 | } 2094 | layer { 2095 | name: "loc1/conv" 2096 | type: "Convolution" 2097 | bottom: "stage4_8/sum" 2098 | top: "loc1/conv" 2099 | param { 2100 | lr_mult: 1.0 2101 | decay_mult: 1.0 2102 | } 2103 | param { 2104 | lr_mult: 1.0 2105 | decay_mult: 0.0 2106 | } 2107 | convolution_param { 2108 | num_output: 24 2109 | bias_term: true 2110 | pad: 0 2111 | kernel_size: 1 2112 | group: 1 2113 | stride: 1 2114 | weight_filler { 2115 | type: "msra" 2116 | } 2117 | dilation: 1 2118 | } 2119 | } 2120 | layer { 2121 | name: "loc1/permute" 2122 | type: "Permute" 2123 | bottom: "loc1/conv" 2124 | top: "loc1/permute" 2125 | permute_param { 2126 | order: 0 2127 | order: 2 2128 | order: 3 2129 | order: 1 2130 | } 2131 | } 2132 | layer { 2133 | name: "loc1/flatten" 2134 | type: "Flatten" 2135 | bottom: "loc1/permute" 2136 | top: "loc1/flatten" 2137 | flatten_param { 2138 | axis: 1 2139 | } 2140 | } 2141 | layer { 2142 | name: "stage4_8/sum/prior_box" 2143 | type: "PriorBox" 2144 | bottom: "stage4_8/sum" 2145 | bottom: "data" 2146 | top: "stage4_8/sum/prior_box" 2147 | prior_box_param { 2148 | min_size: 50.0 2149 | max_size: 100.0 2150 | aspect_ratio: 2.0 2151 | aspect_ratio: 0.5 2152 | aspect_ratio: 3.0 2153 | aspect_ratio: 0.3333333432674408 2154 | flip: false 2155 | clip: false 2156 | variance: 0.10000000149011612 2157 | variance: 0.10000000149011612 2158 | variance: 0.20000000298023224 2159 | variance: 0.20000000298023224 2160 | step: 16.0 2161 | } 2162 | } 2163 | layer { 2164 | name: "cls2/conv" 2165 | type: "Convolution" 2166 | bottom: "stage5_4/sum" 2167 | top: "cls2/conv" 2168 | param { 2169 | lr_mult: 1.0 2170 | decay_mult: 1.0 2171 | } 2172 | param { 2173 | lr_mult: 1.0 2174 | decay_mult: 0.0 2175 | } 2176 | convolution_param { 2177 | num_output: 12 2178 | bias_term: true 2179 | pad: 0 2180 | kernel_size: 1 2181 | group: 1 2182 | stride: 1 2183 | weight_filler { 2184 | type: "msra" 2185 | } 2186 | dilation: 1 2187 | } 2188 | } 2189 | layer { 2190 | name: "cls2/permute" 2191 | type: "Permute" 2192 | bottom: "cls2/conv" 2193 | top: "cls2/permute" 2194 | permute_param { 2195 | order: 0 2196 | order: 2 2197 | order: 3 2198 | order: 1 2199 | } 2200 | } 2201 | layer { 2202 | name: "cls2/flatten" 2203 | type: "Flatten" 2204 | bottom: "cls2/permute" 2205 | top: "cls2/flatten" 2206 | flatten_param { 2207 | axis: 1 2208 | } 2209 | } 2210 | layer { 2211 | name: "loc2/conv" 2212 | type: "Convolution" 2213 | bottom: "stage5_4/sum" 2214 | top: "loc2/conv" 2215 | param { 2216 | lr_mult: 1.0 2217 | decay_mult: 1.0 2218 | } 2219 | param { 2220 | lr_mult: 1.0 2221 | decay_mult: 0.0 2222 | } 2223 | convolution_param { 2224 | num_output: 24 2225 | bias_term: true 2226 | pad: 0 2227 | kernel_size: 1 2228 | group: 1 2229 | stride: 1 2230 | weight_filler { 2231 | type: "msra" 2232 | } 2233 | dilation: 1 2234 | } 2235 | } 2236 | layer { 2237 | name: "loc2/permute" 2238 | type: "Permute" 2239 | bottom: "loc2/conv" 2240 | top: "loc2/permute" 2241 | permute_param { 2242 | order: 0 2243 | order: 2 2244 | order: 3 2245 | order: 1 2246 | } 2247 | } 2248 | layer { 2249 | name: "loc2/flatten" 2250 | type: "Flatten" 2251 | bottom: "loc2/permute" 2252 | top: "loc2/flatten" 2253 | flatten_param { 2254 | axis: 1 2255 | } 2256 | } 2257 | layer { 2258 | name: "stage5_4/sum/prior_box" 2259 | type: "PriorBox" 2260 | bottom: "stage5_4/sum" 2261 | bottom: "data" 2262 | top: "stage5_4/sum/prior_box" 2263 | prior_box_param { 2264 | min_size: 100.0 2265 | max_size: 150.0 2266 | aspect_ratio: 2.0 2267 | aspect_ratio: 0.5 2268 | aspect_ratio: 3.0 2269 | aspect_ratio: 0.3333333432674408 2270 | flip: false 2271 | clip: false 2272 | variance: 0.10000000149011612 2273 | variance: 0.10000000149011612 2274 | variance: 0.20000000298023224 2275 | variance: 0.20000000298023224 2276 | step: 32.0 2277 | } 2278 | } 2279 | layer { 2280 | name: "cls3/conv" 2281 | type: "Convolution" 2282 | bottom: "stage6_2/sum" 2283 | top: "cls3/conv" 2284 | param { 2285 | lr_mult: 1.0 2286 | decay_mult: 1.0 2287 | } 2288 | param { 2289 | lr_mult: 1.0 2290 | decay_mult: 0.0 2291 | } 2292 | convolution_param { 2293 | num_output: 12 2294 | bias_term: true 2295 | pad: 0 2296 | kernel_size: 1 2297 | group: 1 2298 | stride: 1 2299 | weight_filler { 2300 | type: "msra" 2301 | } 2302 | dilation: 1 2303 | } 2304 | } 2305 | layer { 2306 | name: "cls3/permute" 2307 | type: "Permute" 2308 | bottom: "cls3/conv" 2309 | top: "cls3/permute" 2310 | permute_param { 2311 | order: 0 2312 | order: 2 2313 | order: 3 2314 | order: 1 2315 | } 2316 | } 2317 | layer { 2318 | name: "cls3/flatten" 2319 | type: "Flatten" 2320 | bottom: "cls3/permute" 2321 | top: "cls3/flatten" 2322 | flatten_param { 2323 | axis: 1 2324 | } 2325 | } 2326 | layer { 2327 | name: "loc3/conv" 2328 | type: "Convolution" 2329 | bottom: "stage6_2/sum" 2330 | top: "loc3/conv" 2331 | param { 2332 | lr_mult: 1.0 2333 | decay_mult: 1.0 2334 | } 2335 | param { 2336 | lr_mult: 1.0 2337 | decay_mult: 0.0 2338 | } 2339 | convolution_param { 2340 | num_output: 24 2341 | bias_term: true 2342 | pad: 0 2343 | kernel_size: 1 2344 | group: 1 2345 | stride: 1 2346 | weight_filler { 2347 | type: "msra" 2348 | } 2349 | dilation: 1 2350 | } 2351 | } 2352 | layer { 2353 | name: "loc3/permute" 2354 | type: "Permute" 2355 | bottom: "loc3/conv" 2356 | top: "loc3/permute" 2357 | permute_param { 2358 | order: 0 2359 | order: 2 2360 | order: 3 2361 | order: 1 2362 | } 2363 | } 2364 | layer { 2365 | name: "loc3/flatten" 2366 | type: "Flatten" 2367 | bottom: "loc3/permute" 2368 | top: "loc3/flatten" 2369 | flatten_param { 2370 | axis: 1 2371 | } 2372 | } 2373 | layer { 2374 | name: "stage6_2/sum/prior_box" 2375 | type: "PriorBox" 2376 | bottom: "stage6_2/sum" 2377 | bottom: "data" 2378 | top: "stage6_2/sum/prior_box" 2379 | prior_box_param { 2380 | min_size: 150.0 2381 | max_size: 200.0 2382 | aspect_ratio: 2.0 2383 | aspect_ratio: 0.5 2384 | aspect_ratio: 3.0 2385 | aspect_ratio: 0.3333333432674408 2386 | flip: false 2387 | clip: false 2388 | variance: 0.10000000149011612 2389 | variance: 0.10000000149011612 2390 | variance: 0.20000000298023224 2391 | variance: 0.20000000298023224 2392 | step: 32.0 2393 | } 2394 | } 2395 | layer { 2396 | name: "cls4/conv" 2397 | type: "Convolution" 2398 | bottom: "stage7_2/sum" 2399 | top: "cls4/conv" 2400 | param { 2401 | lr_mult: 1.0 2402 | decay_mult: 1.0 2403 | } 2404 | param { 2405 | lr_mult: 1.0 2406 | decay_mult: 0.0 2407 | } 2408 | convolution_param { 2409 | num_output: 12 2410 | bias_term: true 2411 | pad: 0 2412 | kernel_size: 1 2413 | group: 1 2414 | stride: 1 2415 | weight_filler { 2416 | type: "msra" 2417 | } 2418 | dilation: 1 2419 | } 2420 | } 2421 | layer { 2422 | name: "cls4/permute" 2423 | type: "Permute" 2424 | bottom: "cls4/conv" 2425 | top: "cls4/permute" 2426 | permute_param { 2427 | order: 0 2428 | order: 2 2429 | order: 3 2430 | order: 1 2431 | } 2432 | } 2433 | layer { 2434 | name: "cls4/flatten" 2435 | type: "Flatten" 2436 | bottom: "cls4/permute" 2437 | top: "cls4/flatten" 2438 | flatten_param { 2439 | axis: 1 2440 | } 2441 | } 2442 | layer { 2443 | name: "loc4/conv" 2444 | type: "Convolution" 2445 | bottom: "stage7_2/sum" 2446 | top: "loc4/conv" 2447 | param { 2448 | lr_mult: 1.0 2449 | decay_mult: 1.0 2450 | } 2451 | param { 2452 | lr_mult: 1.0 2453 | decay_mult: 0.0 2454 | } 2455 | convolution_param { 2456 | num_output: 24 2457 | bias_term: true 2458 | pad: 0 2459 | kernel_size: 1 2460 | group: 1 2461 | stride: 1 2462 | weight_filler { 2463 | type: "msra" 2464 | } 2465 | dilation: 1 2466 | } 2467 | } 2468 | layer { 2469 | name: "loc4/permute" 2470 | type: "Permute" 2471 | bottom: "loc4/conv" 2472 | top: "loc4/permute" 2473 | permute_param { 2474 | order: 0 2475 | order: 2 2476 | order: 3 2477 | order: 1 2478 | } 2479 | } 2480 | layer { 2481 | name: "loc4/flatten" 2482 | type: "Flatten" 2483 | bottom: "loc4/permute" 2484 | top: "loc4/flatten" 2485 | flatten_param { 2486 | axis: 1 2487 | } 2488 | } 2489 | layer { 2490 | name: "stage7_2/sum/prior_box" 2491 | type: "PriorBox" 2492 | bottom: "stage7_2/sum" 2493 | bottom: "data" 2494 | top: "stage7_2/sum/prior_box" 2495 | prior_box_param { 2496 | min_size: 200.0 2497 | max_size: 300.0 2498 | aspect_ratio: 2.0 2499 | aspect_ratio: 0.5 2500 | aspect_ratio: 3.0 2501 | aspect_ratio: 0.3333333432674408 2502 | flip: false 2503 | clip: false 2504 | variance: 0.10000000149011612 2505 | variance: 0.10000000149011612 2506 | variance: 0.20000000298023224 2507 | variance: 0.20000000298023224 2508 | step: 32.0 2509 | } 2510 | } 2511 | layer { 2512 | name: "cls5/conv" 2513 | type: "Convolution" 2514 | bottom: "stage8_2/sum" 2515 | top: "cls5/conv" 2516 | param { 2517 | lr_mult: 1.0 2518 | decay_mult: 1.0 2519 | } 2520 | param { 2521 | lr_mult: 1.0 2522 | decay_mult: 0.0 2523 | } 2524 | convolution_param { 2525 | num_output: 12 2526 | bias_term: true 2527 | pad: 0 2528 | kernel_size: 1 2529 | group: 1 2530 | stride: 1 2531 | weight_filler { 2532 | type: "msra" 2533 | } 2534 | dilation: 1 2535 | } 2536 | } 2537 | layer { 2538 | name: "cls5/permute" 2539 | type: "Permute" 2540 | bottom: "cls5/conv" 2541 | top: "cls5/permute" 2542 | permute_param { 2543 | order: 0 2544 | order: 2 2545 | order: 3 2546 | order: 1 2547 | } 2548 | } 2549 | layer { 2550 | name: "cls5/flatten" 2551 | type: "Flatten" 2552 | bottom: "cls5/permute" 2553 | top: "cls5/flatten" 2554 | flatten_param { 2555 | axis: 1 2556 | } 2557 | } 2558 | layer { 2559 | name: "loc5/conv" 2560 | type: "Convolution" 2561 | bottom: "stage8_2/sum" 2562 | top: "loc5/conv" 2563 | param { 2564 | lr_mult: 1.0 2565 | decay_mult: 1.0 2566 | } 2567 | param { 2568 | lr_mult: 1.0 2569 | decay_mult: 0.0 2570 | } 2571 | convolution_param { 2572 | num_output: 24 2573 | bias_term: true 2574 | pad: 0 2575 | kernel_size: 1 2576 | group: 1 2577 | stride: 1 2578 | weight_filler { 2579 | type: "msra" 2580 | } 2581 | dilation: 1 2582 | } 2583 | } 2584 | layer { 2585 | name: "loc5/permute" 2586 | type: "Permute" 2587 | bottom: "loc5/conv" 2588 | top: "loc5/permute" 2589 | permute_param { 2590 | order: 0 2591 | order: 2 2592 | order: 3 2593 | order: 1 2594 | } 2595 | } 2596 | layer { 2597 | name: "loc5/flatten" 2598 | type: "Flatten" 2599 | bottom: "loc5/permute" 2600 | top: "loc5/flatten" 2601 | flatten_param { 2602 | axis: 1 2603 | } 2604 | } 2605 | layer { 2606 | name: "stage8_2/sum/prior_box" 2607 | type: "PriorBox" 2608 | bottom: "stage8_2/sum" 2609 | bottom: "data" 2610 | top: "stage8_2/sum/prior_box" 2611 | prior_box_param { 2612 | min_size: 300.0 2613 | max_size: 400.0 2614 | aspect_ratio: 2.0 2615 | aspect_ratio: 0.5 2616 | aspect_ratio: 3.0 2617 | aspect_ratio: 0.3333333432674408 2618 | flip: false 2619 | clip: false 2620 | variance: 0.10000000149011612 2621 | variance: 0.10000000149011612 2622 | variance: 0.20000000298023224 2623 | variance: 0.20000000298023224 2624 | step: 32.0 2625 | } 2626 | } 2627 | layer { 2628 | name: "mbox_conf" 2629 | type: "Concat" 2630 | bottom: "cls1/flatten" 2631 | bottom: "cls2/flatten" 2632 | bottom: "cls3/flatten" 2633 | bottom: "cls4/flatten" 2634 | bottom: "cls5/flatten" 2635 | top: "mbox_conf" 2636 | concat_param { 2637 | axis: 1 2638 | } 2639 | } 2640 | layer { 2641 | name: "mbox_loc" 2642 | type: "Concat" 2643 | bottom: "loc1/flatten" 2644 | bottom: "loc2/flatten" 2645 | bottom: "loc3/flatten" 2646 | bottom: "loc4/flatten" 2647 | bottom: "loc5/flatten" 2648 | top: "mbox_loc" 2649 | concat_param { 2650 | axis: 1 2651 | } 2652 | } 2653 | layer { 2654 | name: "mbox_priorbox" 2655 | type: "Concat" 2656 | bottom: "stage4_8/sum/prior_box" 2657 | bottom: "stage5_4/sum/prior_box" 2658 | bottom: "stage6_2/sum/prior_box" 2659 | bottom: "stage7_2/sum/prior_box" 2660 | bottom: "stage8_2/sum/prior_box" 2661 | top: "mbox_priorbox" 2662 | concat_param { 2663 | axis: 2 2664 | } 2665 | } 2666 | layer { 2667 | name: "mbox_conf_reshape" 2668 | type: "Reshape" 2669 | bottom: "mbox_conf" 2670 | top: "mbox_conf_reshape" 2671 | reshape_param { 2672 | shape { 2673 | dim: 0 2674 | dim: -1 2675 | dim: 2 2676 | } 2677 | } 2678 | } 2679 | layer { 2680 | name: "mbox_conf_softmax" 2681 | type: "Softmax" 2682 | bottom: "mbox_conf_reshape" 2683 | top: "mbox_conf_softmax" 2684 | softmax_param { 2685 | axis: 2 2686 | } 2687 | } 2688 | layer { 2689 | name: "mbox_conf_flatten" 2690 | type: "Flatten" 2691 | bottom: "mbox_conf_softmax" 2692 | top: "mbox_conf_flatten" 2693 | flatten_param { 2694 | axis: 1 2695 | } 2696 | } 2697 | layer { 2698 | name: "detection_output" 2699 | type: "DetectionOutput" 2700 | bottom: "mbox_loc" 2701 | bottom: "mbox_conf_flatten" 2702 | bottom: "mbox_priorbox" 2703 | top: "detection_output" 2704 | detection_output_param { 2705 | num_classes: 2 2706 | share_location: true 2707 | background_label_id: 0 2708 | nms_param { 2709 | nms_threshold: 0.44999998807907104 2710 | top_k: 100 2711 | } 2712 | code_type: CENTER_SIZE 2713 | keep_top_k: 100 2714 | confidence_threshold: 0.20000000298023224 2715 | } 2716 | } 2717 | -------------------------------------------------------------------------------- /models/sr.caffemodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zfb132/QrScan/dfc1e63ea0beaf57930810c73576f83e91cdc607/models/sr.caffemodel -------------------------------------------------------------------------------- /models/sr.prototxt: -------------------------------------------------------------------------------- 1 | layer { 2 | name: "data" 3 | type: "Input" 4 | top: "data" 5 | input_param { 6 | shape { 7 | dim: 1 8 | dim: 1 9 | dim: 224 10 | dim: 224 11 | } 12 | } 13 | } 14 | layer { 15 | name: "conv0" 16 | type: "Convolution" 17 | bottom: "data" 18 | top: "conv0" 19 | param { 20 | lr_mult: 1.0 21 | decay_mult: 1.0 22 | } 23 | param { 24 | lr_mult: 1.0 25 | decay_mult: 0.0 26 | } 27 | convolution_param { 28 | num_output: 32 29 | bias_term: true 30 | pad: 1 31 | kernel_size: 3 32 | group: 1 33 | stride: 1 34 | weight_filler { 35 | type: "msra" 36 | } 37 | } 38 | } 39 | layer { 40 | name: "conv0/lrelu" 41 | type: "ReLU" 42 | bottom: "conv0" 43 | top: "conv0" 44 | relu_param { 45 | negative_slope: 0.05000000074505806 46 | } 47 | } 48 | layer { 49 | name: "db1/reduce" 50 | type: "Convolution" 51 | bottom: "conv0" 52 | top: "db1/reduce" 53 | param { 54 | lr_mult: 1.0 55 | decay_mult: 1.0 56 | } 57 | param { 58 | lr_mult: 1.0 59 | decay_mult: 0.0 60 | } 61 | convolution_param { 62 | num_output: 8 63 | bias_term: true 64 | pad: 0 65 | kernel_size: 1 66 | group: 1 67 | stride: 1 68 | weight_filler { 69 | type: "msra" 70 | } 71 | } 72 | } 73 | layer { 74 | name: "db1/reduce/lrelu" 75 | type: "ReLU" 76 | bottom: "db1/reduce" 77 | top: "db1/reduce" 78 | relu_param { 79 | negative_slope: 0.05000000074505806 80 | } 81 | } 82 | layer { 83 | name: "db1/3x3" 84 | type: "Convolution" 85 | bottom: "db1/reduce" 86 | top: "db1/3x3" 87 | param { 88 | lr_mult: 1.0 89 | decay_mult: 1.0 90 | } 91 | param { 92 | lr_mult: 1.0 93 | decay_mult: 0.0 94 | } 95 | convolution_param { 96 | num_output: 8 97 | bias_term: true 98 | pad: 1 99 | kernel_size: 3 100 | group: 8 101 | stride: 1 102 | weight_filler { 103 | type: "msra" 104 | } 105 | } 106 | } 107 | layer { 108 | name: "db1/3x3/lrelu" 109 | type: "ReLU" 110 | bottom: "db1/3x3" 111 | top: "db1/3x3" 112 | relu_param { 113 | negative_slope: 0.05000000074505806 114 | } 115 | } 116 | layer { 117 | name: "db1/1x1" 118 | type: "Convolution" 119 | bottom: "db1/3x3" 120 | top: "db1/1x1" 121 | param { 122 | lr_mult: 1.0 123 | decay_mult: 1.0 124 | } 125 | param { 126 | lr_mult: 1.0 127 | decay_mult: 0.0 128 | } 129 | convolution_param { 130 | num_output: 32 131 | bias_term: true 132 | pad: 0 133 | kernel_size: 1 134 | group: 1 135 | stride: 1 136 | weight_filler { 137 | type: "msra" 138 | } 139 | } 140 | } 141 | layer { 142 | name: "db1/1x1/lrelu" 143 | type: "ReLU" 144 | bottom: "db1/1x1" 145 | top: "db1/1x1" 146 | relu_param { 147 | negative_slope: 0.05000000074505806 148 | } 149 | } 150 | layer { 151 | name: "db1/concat" 152 | type: "Concat" 153 | bottom: "conv0" 154 | bottom: "db1/1x1" 155 | top: "db1/concat" 156 | concat_param { 157 | axis: 1 158 | } 159 | } 160 | layer { 161 | name: "db2/reduce" 162 | type: "Convolution" 163 | bottom: "db1/concat" 164 | top: "db2/reduce" 165 | param { 166 | lr_mult: 1.0 167 | decay_mult: 1.0 168 | } 169 | param { 170 | lr_mult: 1.0 171 | decay_mult: 0.0 172 | } 173 | convolution_param { 174 | num_output: 8 175 | bias_term: true 176 | pad: 0 177 | kernel_size: 1 178 | group: 1 179 | stride: 1 180 | weight_filler { 181 | type: "msra" 182 | } 183 | } 184 | } 185 | layer { 186 | name: "db2/reduce/lrelu" 187 | type: "ReLU" 188 | bottom: "db2/reduce" 189 | top: "db2/reduce" 190 | relu_param { 191 | negative_slope: 0.05000000074505806 192 | } 193 | } 194 | layer { 195 | name: "db2/3x3" 196 | type: "Convolution" 197 | bottom: "db2/reduce" 198 | top: "db2/3x3" 199 | param { 200 | lr_mult: 1.0 201 | decay_mult: 1.0 202 | } 203 | param { 204 | lr_mult: 1.0 205 | decay_mult: 0.0 206 | } 207 | convolution_param { 208 | num_output: 8 209 | bias_term: true 210 | pad: 1 211 | kernel_size: 3 212 | group: 8 213 | stride: 1 214 | weight_filler { 215 | type: "msra" 216 | } 217 | } 218 | } 219 | layer { 220 | name: "db2/3x3/lrelu" 221 | type: "ReLU" 222 | bottom: "db2/3x3" 223 | top: "db2/3x3" 224 | relu_param { 225 | negative_slope: 0.05000000074505806 226 | } 227 | } 228 | layer { 229 | name: "db2/1x1" 230 | type: "Convolution" 231 | bottom: "db2/3x3" 232 | top: "db2/1x1" 233 | param { 234 | lr_mult: 1.0 235 | decay_mult: 1.0 236 | } 237 | param { 238 | lr_mult: 1.0 239 | decay_mult: 0.0 240 | } 241 | convolution_param { 242 | num_output: 32 243 | bias_term: true 244 | pad: 0 245 | kernel_size: 1 246 | group: 1 247 | stride: 1 248 | weight_filler { 249 | type: "msra" 250 | } 251 | } 252 | } 253 | layer { 254 | name: "db2/1x1/lrelu" 255 | type: "ReLU" 256 | bottom: "db2/1x1" 257 | top: "db2/1x1" 258 | relu_param { 259 | negative_slope: 0.05000000074505806 260 | } 261 | } 262 | layer { 263 | name: "db2/concat" 264 | type: "Concat" 265 | bottom: "db1/concat" 266 | bottom: "db2/1x1" 267 | top: "db2/concat" 268 | concat_param { 269 | axis: 1 270 | } 271 | } 272 | layer { 273 | name: "upsample/reduce" 274 | type: "Convolution" 275 | bottom: "db2/concat" 276 | top: "upsample/reduce" 277 | param { 278 | lr_mult: 1.0 279 | decay_mult: 1.0 280 | } 281 | param { 282 | lr_mult: 1.0 283 | decay_mult: 0.0 284 | } 285 | convolution_param { 286 | num_output: 32 287 | bias_term: true 288 | pad: 0 289 | kernel_size: 1 290 | group: 1 291 | stride: 1 292 | weight_filler { 293 | type: "msra" 294 | } 295 | } 296 | } 297 | layer { 298 | name: "upsample/reduce/lrelu" 299 | type: "ReLU" 300 | bottom: "upsample/reduce" 301 | top: "upsample/reduce" 302 | relu_param { 303 | negative_slope: 0.05000000074505806 304 | } 305 | } 306 | layer { 307 | name: "upsample/deconv" 308 | type: "Deconvolution" 309 | bottom: "upsample/reduce" 310 | top: "upsample/deconv" 311 | param { 312 | lr_mult: 1.0 313 | decay_mult: 1.0 314 | } 315 | param { 316 | lr_mult: 1.0 317 | decay_mult: 0.0 318 | } 319 | convolution_param { 320 | num_output: 32 321 | bias_term: true 322 | pad: 1 323 | kernel_size: 3 324 | group: 32 325 | stride: 2 326 | weight_filler { 327 | type: "msra" 328 | } 329 | } 330 | } 331 | layer { 332 | name: "upsample/lrelu" 333 | type: "ReLU" 334 | bottom: "upsample/deconv" 335 | top: "upsample/deconv" 336 | relu_param { 337 | negative_slope: 0.05000000074505806 338 | } 339 | } 340 | layer { 341 | name: "upsample/rec" 342 | type: "Convolution" 343 | bottom: "upsample/deconv" 344 | top: "upsample/rec" 345 | param { 346 | lr_mult: 1.0 347 | decay_mult: 1.0 348 | } 349 | param { 350 | lr_mult: 1.0 351 | decay_mult: 0.0 352 | } 353 | convolution_param { 354 | num_output: 1 355 | bias_term: true 356 | pad: 0 357 | kernel_size: 1 358 | group: 1 359 | stride: 1 360 | weight_filler { 361 | type: "msra" 362 | } 363 | } 364 | } 365 | layer { 366 | name: "nearest" 367 | type: "Deconvolution" 368 | bottom: "data" 369 | top: "nearest" 370 | param { 371 | lr_mult: 0.0 372 | decay_mult: 0.0 373 | } 374 | convolution_param { 375 | num_output: 1 376 | bias_term: false 377 | pad: 0 378 | kernel_size: 2 379 | group: 1 380 | stride: 2 381 | weight_filler { 382 | type: "constant" 383 | value: 1.0 384 | } 385 | } 386 | } 387 | layer { 388 | name: "Crop1" 389 | type: "Crop" 390 | bottom: "nearest" 391 | bottom: "upsample/rec" 392 | top: "Crop1" 393 | } 394 | layer { 395 | name: "fc" 396 | type: "Eltwise" 397 | bottom: "Crop1" 398 | bottom: "upsample/rec" 399 | top: "fc" 400 | eltwise_param { 401 | operation: SUM 402 | } 403 | } 404 | -------------------------------------------------------------------------------- /pyqt5_qr_scan.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # author: 'zfb' 4 | # time: 2022-02-20 11:18 5 | 6 | from PyQt5.QtCore import Qt 7 | from PyQt5.QtWidgets import QApplication 8 | from PyQt5.QtGui import QIcon 9 | 10 | from multiprocessing import freeze_support 11 | import sys 12 | import os 13 | import logging 14 | 15 | from custom_qwidget import QrDetectDialog, scan_process 16 | from sql_helper import create_files_table, create_status_table 17 | from utils import get_base_path 18 | 19 | # 用于把图片资源嵌入到Qt程序里面 20 | # 发布exe时就不需要附该文件了 21 | import resources 22 | 23 | def log_init(): 24 | try: 25 | # 当前程序的路径 26 | log_dir = os.path.join(get_base_path(), "log") 27 | if not os.path.exists(log_dir): 28 | os.makedirs(log_dir) 29 | logging.info(f"日志文件夹{log_dir}创建成功") 30 | else: 31 | logging.info(f"日志文件夹{log_dir}已存在") 32 | except Exception as e: 33 | logging.warning(f"日志文件{log_dir}创建失败") 34 | logging.warning(repr(e)) 35 | 36 | if __name__ == '__main__': 37 | # 如果用pyinstaller打包含有多进程的代码,这一行必须要 38 | # 且在最开始执行 39 | freeze_support() 40 | create_files_table() 41 | create_status_table() 42 | app = QApplication(sys.argv) 43 | detectDialog = QrDetectDialog() 44 | detectDialog.set_run_func(scan_process) 45 | detectDialog.setWindowFlags(Qt.WindowMinimizeButtonHint|Qt.WindowCloseButtonHint) 46 | detectDialog.setWindowIcon(QIcon(':/icons/icon.png')) 47 | screen = app.desktop() 48 | detectDialog.resize(screen.height(),screen.height()//2) 49 | fg = detectDialog.frameGeometry() 50 | sc = screen.availableGeometry().center() 51 | fg.moveCenter(sc) 52 | detectDialog.show() 53 | log_init() 54 | code = app.exec_() 55 | if detectDialog._loadThread: 56 | detectDialog._loadThread.quit() 57 | sys.exit(code) -------------------------------------------------------------------------------- /qrscan.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zfb132/QrScan/dfc1e63ea0beaf57930810c73576f83e91cdc607/qrscan.ico -------------------------------------------------------------------------------- /qrscan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zfb132/QrScan/dfc1e63ea0beaf57930810c73576f83e91cdc607/qrscan.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyqt5 2 | pyinstaller>=6.3 3 | opencv-python==4.6.0.66 4 | opencv-contrib-python==4.6.0.66 5 | pycryptodome 6 | tinyaes -------------------------------------------------------------------------------- /resources.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Resource object code 4 | # 5 | # Created by: The Resource Compiler for PyQt5 (Qt v5.15.2) 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore 10 | 11 | qt_resource_data = b"\ 12 | \x00\x00\x29\xad\ 13 | \x89\ 14 | \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ 15 | \x00\x01\x90\x00\x00\x01\x90\x08\x02\x00\x00\x00\x0f\xdd\xa1\x9b\ 16 | \x00\x00\x00\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\ 17 | \x00\x00\x00\x20\x63\x48\x52\x4d\x00\x00\x7a\x26\x00\x00\x80\x84\ 18 | \x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00\x75\x30\x00\x00\xea\x60\ 19 | \x00\x00\x3a\x98\x00\x00\x17\x70\x9c\xba\x51\x3c\x00\x00\x00\x06\ 20 | \x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\ 21 | \x29\x26\x49\x44\x41\x54\x78\xda\xed\xdd\x7b\x70\x1c\xd5\x9d\x2f\ 22 | \xf0\xdf\xe9\xee\x79\x8f\x35\x7a\x58\xc2\x0f\x02\xb6\x85\x30\x18\ 23 | \x5b\x16\x08\x1c\xdb\xe2\xa6\x02\x75\x6d\x08\x31\x64\x79\x5e\x2a\ 24 | \xc4\xd9\x38\x0e\x7f\x00\x7b\x9d\x18\x16\x02\xb5\xe4\x02\x55\x81\ 25 | \x78\x8b\x64\x49\xa8\xdd\x4a\x15\x81\xc4\xd7\xd7\x09\xa9\x10\x02\ 26 | \xe1\xb5\x90\xb5\xaf\x6e\x1c\x6c\xcc\x43\x85\x25\xbf\x00\x21\x64\ 27 | \x1c\x3f\x25\xeb\x31\xa3\xd1\xcc\x68\xa6\xfb\x9c\xfb\xc7\xc8\x46\ 28 | \x96\xad\x91\x34\xd3\xd3\x7d\xce\xe8\xfb\x29\xf2\x28\x66\xa6\xfb\ 29 | \x74\xf7\x99\xaf\x4e\xf7\xfc\xfa\x34\x13\x42\x10\x00\x80\x0a\x34\ 30 | \xb7\x1b\x00\x00\x30\x51\x08\x2c\x00\x50\x06\x02\x0b\x00\x94\x81\ 31 | \xc0\x02\x00\x65\x20\xb0\x00\x40\x19\x08\x2c\x00\x50\x06\x02\x0b\ 32 | \x00\x94\x81\xc0\x02\x00\x65\x20\xb0\x00\x40\x19\x08\x2c\x00\x50\ 33 | \x06\x02\x0b\x00\x94\x81\xc0\x02\x00\x65\x20\xb0\x00\x40\x19\x08\ 34 | \x2c\x00\x50\x06\x02\x0b\x00\x94\x81\xc0\x02\x00\x65\x20\xb0\x00\ 35 | \x40\x19\x08\x2c\x00\x50\x06\x02\x0b\x00\x94\x61\xb8\xdd\x80\xd3\ 36 | \x08\x21\x04\x51\xda\x22\x4b\x48\x3a\xd7\x3c\x27\xf2\xe9\xcc\xab\ 37 | \x11\x63\xcc\xed\xb6\x80\xf2\x84\x10\x43\x16\xa5\xb9\x90\x6d\xe0\ 38 | \xc0\x18\xe9\x8c\x79\x75\x62\x24\x57\x57\x77\x3f\xb0\x12\xa6\x38\ 39 | \x32\x60\x7e\xd2\x67\xb6\xf7\x65\x3a\xfa\xcd\x68\x8a\xa7\x4d\xc1\ 40 | \x2d\x49\x03\x4b\x24\xf9\xca\x05\xa1\x6f\x2e\x0a\x85\x3c\x12\x1d\ 41 | \x45\x50\x54\xff\x90\xd8\xd4\x3a\xb0\xed\x93\xa4\x1e\xd2\x48\xa6\ 42 | \x0e\xcf\x18\x69\x3a\xf3\x1a\x2c\xe2\xd7\x6a\xcb\x8d\xba\x0a\xcf\ 43 | \x85\x15\xc6\xac\x69\x46\xd0\x70\xb9\xdb\xbb\x16\x58\x83\x19\xde\ 44 | \xd6\x9d\xf9\x4b\x67\xaa\xed\xf8\x50\x77\xdc\xea\x4a\xf1\xde\xb4\ 45 | \x48\x5a\xdc\xb2\x48\x23\x92\x36\x0c\x92\x31\xb3\x76\xb6\xcf\x92\ 46 | \xa9\x6f\x81\xba\x32\x5c\x7c\xd4\x63\xbe\xdc\x91\x0c\x96\xe9\x6e\ 47 | \xb7\x65\x34\x41\xc4\x89\x74\x9d\x02\xba\x56\xe9\x65\x35\x7e\xad\ 48 | \x3a\xac\xd7\x9f\xe3\x5b\x39\xd7\x5f\x5f\xed\x09\x79\xdc\x19\x14\ 49 | \xba\x10\x58\x47\x07\xad\x97\xda\x13\x6f\xb5\x27\x3a\xfa\xcc\xa3\ 50 | \x29\x9e\xb6\x04\x13\xc4\x34\xd2\x34\xe6\xd5\x98\xa6\x13\x93\x6a\ 51 | \x0c\x7a\xba\x21\xbf\x5e\xe6\xd3\x64\x1b\xc0\x83\xa2\x0c\x8d\xc2\ 52 | \x7e\x4d\xf7\x6b\x21\x9f\x26\xdb\x1f\x41\x41\x24\x84\xe0\x82\x32\ 53 | \x5c\x1c\x4d\xf0\x23\x71\x4b\xf4\x64\xfe\xdf\xa1\xa1\x17\xf6\xc6\ 54 | \x6b\x2b\x8c\x6b\xea\x82\x37\xd6\x05\x67\x86\x9c\xce\x59\x47\x03\ 55 | \xeb\xf8\xa0\xb5\x69\xef\xe0\x8b\xfb\x06\x0f\xc4\xcc\x41\x4b\xe8\ 56 | \x8c\x74\x8d\x05\x3c\x9a\xbc\xf9\x74\x26\x49\x4f\x55\x41\x5d\x62\ 57 | \xf8\x3f\x92\xc9\x5e\xbd\xd2\xb2\xdf\x4d\x9d\x11\x91\x10\x64\x71\ 58 | \x71\x28\x61\x7d\x3e\x68\xbd\x7b\x34\xbd\x69\x57\xfc\xe6\x05\xa1\ 59 | \x6f\x5f\x12\x3a\xc7\xc1\xd8\x72\x28\xb0\x92\x19\xfe\x4a\x47\xf2\ 60 | \x17\xef\xc6\xda\x7b\x33\x43\x8c\x3c\x1a\xf3\x7b\x98\x52\x41\x05\ 61 | \x30\xd5\x31\x46\x86\xce\x0c\x9d\x71\x21\x32\x9c\xf6\xf5\x67\x3a\ 62 | \xb6\xf7\xbf\xb4\x7f\xf0\xfb\x5f\x2e\xbb\xa1\x36\x10\x70\xe4\x24\ 63 | \xb1\xe8\x81\x25\x04\x7d\x1e\x33\x9f\xdc\x19\xfd\xc3\xde\xc1\x41\ 64 | \xa2\xa0\x87\xf9\xd9\xf0\xef\x0e\x42\x10\x22\x0b\x40\x2d\x42\x90\ 65 | \xc6\x98\xa6\x93\xae\x11\x17\xb4\xab\x27\xf3\x4f\x6f\xf4\x6c\xbb\ 66 | \x24\x74\xff\xd2\xc8\xf9\x65\x46\xb1\xbf\xd1\x45\x0c\x45\x21\x28\ 67 | \xc3\xc5\xb6\x43\xa9\xeb\x5f\xe8\xda\xbc\x3b\xce\x0d\x16\xf6\x32\ 68 | \x5d\x63\x8c\xb1\xec\x69\x15\xd2\x0a\x40\x39\xd9\xaf\xad\x10\xc4\ 69 | \x18\xd3\x35\x16\xf6\x32\x6e\xb0\xcd\xbb\xe3\xd7\xbf\xd0\xb5\xed\ 70 | \x50\x2a\xc3\x8b\x7b\xd1\xa4\x58\x23\x2c\x21\x44\xca\xa2\xff\xec\ 71 | \x48\xde\xf9\xc6\x89\x41\x4b\x94\xf9\xb5\x91\xa3\xaa\x53\x51\x25\ 72 | \x46\xfc\x20\xf8\x45\xe9\x95\x84\x27\xf4\x5f\x34\x92\x38\xae\x62\ 73 | \x81\x4d\x84\x20\x2e\x48\x0c\x73\xbb\x35\x67\x62\xc3\xff\x75\xea\ 74 | \x67\xb0\x53\x5f\xd8\x91\xb1\x65\xe8\xa4\xfb\xb5\xf6\xfe\xcc\x4d\ 75 | \x7f\xec\xfa\xd5\x75\xd3\xbf\x56\x1b\xf0\xeb\xc5\xaa\xde\x2a\x4a\ 76 | \x60\x09\x21\x12\xa6\xf8\xd3\x47\x89\x75\x6f\xf6\xa4\x0d\x16\x09\ 77 | \x68\x44\x4c\x08\xa2\x91\x51\x95\x4d\xae\x93\xbf\x44\x10\x91\xc9\ 78 | \xc9\x14\x82\x04\x33\x2c\xc1\x48\xc8\x39\xfc\x0a\xa5\x78\x34\xc1\ 79 | \x51\xd6\x00\xb6\xc8\x70\x1a\x48\xf0\x40\x92\x9b\x92\x95\xf5\x09\ 80 | \x22\x41\xcc\xd4\x19\x31\x61\x30\x66\x68\x82\x88\xb4\x33\x2e\xe6\ 81 | \x30\x36\xfc\x93\x01\x63\x2c\x12\xd0\xe2\x69\xb1\xf6\x95\xee\xa7\ 82 | \xaf\xad\xba\xe9\xa2\x60\xd0\x28\x4a\x66\x31\xdb\x83\x3d\x5b\xbc\ 83 | \xfb\xc2\xfe\xc1\x75\x6f\xf6\x70\xaf\xe6\x37\x68\x54\x59\xd5\xa9\ 84 | \xad\xe5\x42\x90\xa0\x34\x27\x66\x89\x80\xc6\xc2\x21\x6d\x71\x8d\ 85 | \x77\x7e\xa5\x67\x7e\x85\x11\xf1\x69\xba\x7c\xb5\x03\x8c\x28\x99\ 86 | \x11\x17\x4f\xf7\xcc\xaf\xf4\x18\x9a\x5c\x3d\x0c\x54\x34\x64\x89\ 87 | \xfd\x27\x32\xed\x7d\x99\xa0\x87\x49\xf5\x47\xd0\xe2\x14\x1d\xe2\ 88 | \x1f\xf7\x99\x1f\xf7\x66\x5a\xbb\xd2\xf1\x41\x9e\xe4\x42\xe8\xcc\ 89 | \xab\x11\x31\xd2\xc6\xbc\x06\x2d\x52\x26\x69\x69\xfe\xf4\xb5\x55\ 90 | \xb7\x5e\x1c\xf2\x15\x61\x9c\x65\x7f\x60\x99\x5c\xbc\xf1\x69\xf2\ 91 | \x1f\xff\xdc\x9d\x23\xad\xb2\x03\xe0\xa4\x29\x02\x44\xe7\x96\x1b\ 92 | \x37\xcd\x0f\x5d\x3b\xd7\x5f\x5b\x61\x84\x3d\x9a\xc6\x86\x47\x5e\ 93 | \xd2\x3a\x39\x24\x96\xb9\x8d\xa0\x06\x39\x4f\x04\x87\xdb\x76\xf2\ 94 | \x8c\x35\x9e\xe1\x1d\x7d\xe6\x9b\x9d\xa9\x3f\x7d\x3c\x78\xa8\xdf\ 95 | \x4c\x12\x05\x0c\xc6\x18\x65\x2f\x46\x8f\x95\x59\xff\xfb\x1b\xd5\ 96 | \xd7\x5d\x10\xb0\xfd\xef\xba\xcd\x81\xc5\x85\x78\xe7\xf0\xd0\x37\ 97 | \xfe\xd0\x95\x64\x14\xf6\xb2\x91\x69\x25\x04\x11\x09\xc6\x98\x10\ 98 | \x22\x69\x8a\x20\xd1\x05\x95\x9e\x35\x0d\xd3\xfe\xa1\x2e\x50\xe5\ 99 | \x3f\x35\x9a\x42\x0e\x00\x48\x44\x8c\xa8\x12\xeb\x49\xf1\x97\xdb\ 100 | \x93\xbf\xd9\x35\xf0\x69\x6f\x26\x31\x1c\x5b\xd9\x00\x19\xf5\xb5\ 101 | \x15\xf1\xb4\x08\x08\xfa\xf3\x6d\x35\xcb\x66\xfb\xec\xad\x5e\xb2\ 102 | \x33\xb0\x84\x10\x9f\xc7\xac\xeb\x5f\xe8\x6a\xef\xcf\x64\xaf\x5b\ 103 | \x8d\xdc\xec\x6c\xb3\x2d\x2e\xd2\x69\x3e\x3d\xa8\xdf\xd3\x58\xf6\ 104 | \x9d\x45\xa1\xaa\x80\x74\x77\x24\x00\x40\x0e\x3d\x49\x6b\xe3\xee\ 105 | \xc1\xff\x68\x89\x9d\x48\x58\x5e\xaf\xa6\x6b\x67\x3d\x3d\x14\xd1\ 106 | \x24\xaf\x2b\xf7\xbc\x7a\x6b\xcd\xf9\x65\xba\x8d\xc3\x10\x3b\x03\ 107 | \x6b\xc8\x12\xf7\x6d\xe9\xfd\x3f\x6d\x71\x5f\x40\x1b\xd9\xc4\x93\ 108 | \x1b\x23\x4c\x8b\x34\x4b\x2c\x3f\xd7\x7f\xff\xb2\xb2\x2b\xcf\xf5\ 109 | \x3b\xb0\x73\x01\xa0\x18\xde\x3e\x94\x7a\xf2\x9d\xd8\x8e\x43\x29\ 110 | \xae\x33\x43\xa7\xec\xaf\x6a\x23\x73\x49\x08\x31\x94\xe4\xab\xeb\ 111 | \xc3\x3f\xfb\xef\x95\x3e\xdd\xb6\xc0\xb2\xf3\xca\xf6\xeb\x1d\xc9\ 112 | \x17\xf7\x0d\x1a\x3e\xed\x54\xa5\x15\x8d\x48\xab\xb4\x29\x3c\x5c\ 113 | \x7c\x6b\x61\xf8\x17\xd7\x54\x22\xad\x00\x94\x76\xe5\xb9\xfe\x5f\ 114 | \x5c\x53\xf9\xad\x85\x61\x0f\x17\x69\x53\x10\x09\xc6\xe8\xf4\x6f\ 115 | \x3d\x33\x7c\xda\x8b\xfb\x06\x5f\xef\x48\xda\xb8\x5e\xdb\x02\xab\ 116 | \x27\x69\xfd\x6c\x67\x34\x2a\x68\xf8\xd7\xbd\x11\x03\x2c\x22\x32\ 117 | \x2d\xf2\x0a\xfa\xde\xe2\x69\xff\x72\x65\x64\x4e\x99\xfb\x73\xda\ 118 | \x00\x40\x81\xe6\x94\x19\xff\x72\x65\xe4\x7b\x8b\xa7\x79\x05\x99\ 119 | \x56\xf6\xdf\x9d\x4c\x2c\x46\x44\xa4\x6b\x14\x15\xf4\xb3\x9d\xd1\ 120 | \x9e\xa4\x65\xd7\x4a\x6d\x0b\xac\x4d\x7b\x07\xdb\x7b\xcd\xa0\x67\ 121 | \xb8\x90\x3d\x9b\x57\xd9\xa0\xb5\x2c\xc1\x4c\xf1\xcd\x4b\xc2\x3f\ 122 | \x58\x5a\x36\x1d\x17\xad\x00\x4a\xc5\xf4\x80\xfe\x83\xa5\x65\xdf\ 123 | \xbc\x24\xcc\x4c\x61\x59\xe2\x8b\x9b\x58\x4e\x7e\xf7\x83\x1e\xd6\ 124 | \xde\x6b\x6e\xda\x3b\x68\xd7\x1a\xed\x09\xac\xae\x84\xf5\x87\x3d\ 125 | \x83\x29\x12\xda\xc9\x72\x32\x1a\x51\xc1\x30\x64\x8a\xa6\x2f\xf9\ 126 | \xd7\x7f\x19\x69\x05\x50\x6a\xa6\x07\xf4\xf5\x5f\x2e\x6b\xfa\x92\ 127 | \x7f\xc8\x14\x42\x7c\x71\x62\x98\x0d\x01\x8d\x51\x8a\xc4\x1f\xf6\ 128 | \x0c\x76\x25\xec\x19\x64\xd9\x13\x58\x2f\x7e\x92\x38\x10\x33\x3d\ 129 | \x23\xee\x13\xcc\xb6\x58\x08\x91\x32\xc5\xec\x90\xfe\xc3\xe5\x91\ 130 | \xf3\x70\x26\x08\x50\x8a\xce\x2b\x33\x7e\xb8\x3c\x32\x3b\xa4\xa7\ 131 | \x4e\x66\x56\x56\x76\x90\xe5\xd1\xd8\x81\x98\xf9\xe2\x27\x09\x5b\ 132 | \xd6\x65\x43\x60\x25\x4d\xf1\x66\x7b\x22\x6e\x89\xec\xbc\x76\xa7\ 133 | \x86\x57\x44\xc4\x05\xf9\x05\xdd\x79\xe9\xb4\xe5\xb3\x7d\x6e\xec\ 134 | \x49\x00\x70\xc2\xf2\xd9\xbe\x3b\x2f\x9d\xe6\x17\x94\xbd\xcd\xee\ 135 | \xb4\x41\x96\x46\x71\x4b\xbc\xd9\x9e\x48\x9a\x36\x14\x24\xd8\x10\ 136 | \x58\xbb\xba\xd2\x9f\xf5\x99\x06\x23\xed\x8c\xe1\x55\xda\xa2\x8b\ 137 | \xaa\xbd\xdf\xad\x0f\xbb\xb4\x1b\x01\xc0\x21\xdf\xad\x0f\x5f\x54\ 138 | \xed\x4d\x5b\x34\x6a\x90\xa5\x31\x66\x30\xfa\xac\xcf\xdc\xd5\x95\ 139 | \x2e\x7c\x2d\x36\x04\xd6\x7f\x1d\x48\x1d\x4e\x72\x4d\x3b\xfd\x77\ 140 | \x41\x22\x21\x28\x20\xc4\xda\x86\x70\x85\x5f\xbe\xdb\x02\x01\xc0\ 141 | \x56\x15\x7e\x6d\x6d\x43\x38\x70\xf2\x6e\xa3\x91\xa3\x29\x4d\x63\ 142 | \x87\x93\xfc\xbf\x0e\xa4\x0a\x5f\x4b\xa1\x51\x92\xb6\xc4\xee\xe3\ 143 | \x43\x69\x2e\xb2\x05\xaf\xec\xe4\x7c\x14\x42\x88\x34\xa7\xd9\xe5\ 144 | \x9e\x1b\x2e\x08\xba\xb4\x03\x01\xc0\x51\x37\x5c\x10\x9c\x5d\xee\ 145 | \x49\x73\x12\x42\x8c\x9c\x85\x46\xd7\x58\x9a\x8b\xdd\xc7\x87\xd2\ 146 | \x05\xcf\x73\x52\x68\x60\x1d\x1c\x30\x8f\x0f\x58\xda\x19\xf7\x40\ 147 | \x72\x41\xcc\x12\x37\x5e\x14\x2c\xf7\xe1\xe6\x40\x80\x29\xa1\xdc\ 148 | \xc7\x6e\xbc\x28\xc8\xac\xe1\x09\xa3\x4e\x61\x8c\x34\x41\xc7\x07\ 149 | \xac\x83\x03\x66\x81\xab\x28\x34\xb0\x3e\xe9\x35\xbb\x52\x9c\x9d\ 150 | \x6d\x31\x41\x8d\xae\x9b\x1b\x70\x72\x7f\x01\x80\xbb\xae\x9b\x1b\ 151 | \x08\x9e\x2d\x0d\x98\x46\x5d\x29\xfe\x49\xaf\xdb\x81\xd5\xde\x97\ 152 | \xe9\x4d\x0b\x4d\x1b\x35\x87\x8c\x30\xb9\x08\x87\xf4\x79\xe5\x28\ 153 | \x65\x00\x98\x42\xe6\x95\x1b\xe1\x90\x6e\xf2\xd1\x13\xe7\x68\x1a\ 154 | \xeb\x4d\x8b\xf6\xbe\x4c\x81\xcb\x2f\x34\xb0\x3e\xeb\x37\x93\x26\ 155 | \x1f\x35\xe9\x8d\x20\xb2\x04\x35\xce\xf0\x85\x3d\x4c\xe2\x87\xa2\ 156 | \x02\x80\xbd\x58\xd8\xc3\x1a\x67\xf8\x2c\x31\x7a\x9e\x73\x8d\x51\ 157 | \xd2\xe4\x1d\xfd\xae\x8e\xb0\x84\x10\xfd\x29\x6e\x71\x3a\xcb\x2c\ 158 | \x5d\x16\x2d\x9c\xee\xd1\x18\x9e\x34\x01\x30\x55\x30\x46\x1a\xa3\ 159 | \x85\xd3\x3d\x74\x46\x59\xbb\xc6\xc8\xe2\x14\x4d\xf1\x02\x1f\x89\ 160 | \x50\x50\x60\x0d\x71\x4a\x67\x84\x76\xe6\xb4\x7b\x82\x74\x21\xce\ 161 | \x2b\xd3\x31\xba\x02\x98\x5a\x18\x9d\x57\xa6\xeb\x62\xf4\x10\x8b\ 162 | \x31\xa6\x11\xa5\x4d\x91\x2e\xec\x16\x9d\x82\x02\xcb\xe2\x82\x73\ 163 | \x71\xd6\xb3\x3e\x46\x54\xe6\xc5\xb4\xe7\x00\x53\x4b\xf6\x8b\xaf\ 164 | \x9d\xed\xdf\x33\x22\x6e\x09\xab\xb0\x11\x56\x41\x17\xc5\x85\xa0\ 165 | \xb1\xd6\xce\x88\x8c\x62\x96\x8b\x76\x74\x74\xb4\xb5\xb5\x6d\xdf\ 166 | \xbe\x7d\xf7\xee\xdd\xfb\xf7\xef\xef\xef\xef\x1f\x18\x18\x28\xde\ 167 | \xea\x42\xa1\x50\x45\x45\x45\x5d\x5d\xdd\xa2\x45\x8b\x96\x2f\x5f\ 168 | \xde\xd0\xd0\x30\x7f\xfe\xfc\xfc\x16\x95\xdf\xec\x8b\xb6\xcf\xfd\ 169 | \xed\x64\x33\x72\xac\xcb\xf6\x05\x3a\x29\xef\x83\xa2\x6e\xef\x9d\ 170 | \x08\xaf\x9e\xe3\x70\x53\x81\x1d\xb9\x88\xbf\xe2\x15\xa3\x57\x1d\ 171 | \x3d\x7a\xf4\x99\x67\x9e\x79\xf4\xd1\x47\x8b\xd7\xec\xb3\x1a\x1c\ 172 | \x1c\x1c\x1c\x1c\x3c\x74\xe8\x50\x73\x73\xf3\xd3\x4f\x3f\x9d\xfd\ 173 | \x97\xeb\xd7\xaf\x5f\xb7\x6e\xdd\x9c\x39\x73\x1c\x6e\x0c\x28\x6a\ 174 | \x8a\xf4\xde\xa2\x3e\x56\xa3\x88\xa3\x20\x7b\x1f\x38\x9a\x4e\xa7\ 175 | \x7f\xf4\xa3\x1f\xcd\x9a\x35\xcb\xf9\xe3\x3d\x96\xa7\x9e\x7a\x6a\ 176 | \xee\xdc\xb9\x77\xdf\x7d\x77\x2c\x16\x73\xbb\x2d\x20\xb5\x29\xd5\ 177 | \x7b\x8b\xfa\xa4\x61\x35\xee\xf2\xeb\xec\xec\xac\xaa\xaa\xfa\xf1\ 178 | \x8f\x7f\xec\x76\x43\xce\xe2\x97\xbf\xfc\x65\x24\x12\x69\x6d\x6d\ 179 | \x75\xbb\x21\x20\x29\xf4\x5e\x1b\x29\x10\x58\x9d\x9d\x9d\xf3\xe6\ 180 | \xcd\x8b\xc7\xe3\x6e\x37\x24\x97\x86\x86\x06\x85\x8e\x3a\x38\x06\ 181 | \xbd\xd7\x5e\xb2\x07\x56\x32\x99\xac\xaf\xaf\x77\xbb\x15\x13\xd2\ 182 | \xd0\xd0\xd0\xdb\xdb\xeb\x76\x2b\x40\x22\xe8\xbd\xb6\x93\x3d\xb0\ 183 | \x9e\x78\xe2\x09\xc9\xff\x3a\x8d\xb4\x6e\xdd\x3a\xb7\x9b\x00\x12\ 184 | \x41\xef\xb5\x9d\xd4\x81\x75\xf4\xe8\x51\x39\xcf\xfc\xc7\xf2\xdb\ 185 | \xdf\xfe\x76\xdf\xbe\x7d\x6e\xb7\x02\xa4\x80\xde\x5b\x0c\x52\x07\ 186 | \xd6\x33\xcf\x3c\xe3\x76\x13\x26\x6d\xc3\x86\x0d\x6e\x37\x01\xa4\ 187 | \x80\xde\x5b\x0c\x05\x3d\xf9\x39\x9e\xe6\xdf\x7d\xf5\xc4\x7f\x7e\ 188 | \x9e\x0a\xfa\x4e\x0b\x3e\xce\x85\x35\xc4\x37\xdd\x58\x7d\xdd\xbc\ 189 | \x80\x96\x6f\x35\x16\xe7\x5c\xd7\x27\xf4\x94\x9d\x70\x38\x7c\xc5\ 190 | \x15\x57\x2c\x5c\xb8\xb0\xbe\xbe\xbe\xbe\xbe\xbe\xb6\xb6\x36\x12\ 191 | \x89\x18\x46\x41\x25\x66\xa6\x69\xc6\x62\xb1\xce\xce\xce\xb6\xb6\ 192 | \xb6\xd6\xd6\xd6\x3d\x7b\xf6\x7c\xf0\xc1\x07\xd1\x68\x74\x22\x9f\ 193 | \x4d\x24\x12\x81\x80\x73\xf3\xea\xe4\x57\x96\xe9\x64\x31\x67\x7e\ 194 | \xcd\xc8\xc1\xc9\x72\xd3\xfc\xd6\x35\x65\x7b\x2f\x17\xe2\x8d\xcf\ 195 | \x92\xdf\x7e\xa9\x5b\xf7\x69\xa3\x26\x71\x49\x0c\xf1\xaf\x9d\xef\ 196 | \xff\xf5\xf5\xd3\xc3\xde\xfc\xc7\x49\xf2\x4e\xff\xd2\xd9\xd9\x39\ 197 | \xee\x7b\x74\x5d\x6f\x6a\x6a\x5a\xbb\x76\xed\xca\x95\x2b\x67\xcc\ 198 | \x98\x61\xe3\xda\x0d\xc3\xa8\xac\xac\xac\xac\xac\x6c\x6c\x6c\x24\ 199 | \xa2\xae\xae\xae\xad\x5b\xb7\x6e\xdc\xb8\xb1\xb9\xb9\x39\x93\x19\ 200 | \x67\x8a\x8c\xd6\xd6\xd6\xa5\x4b\x97\xba\xba\xf3\xc0\x65\xe8\xbd\ 201 | \x45\x22\xef\x29\x61\x5b\x5b\x5b\xee\x37\x04\x02\x81\x07\x1f\x7c\ 202 | \xf0\xf9\xe7\x9f\x5f\xbd\x7a\xb5\xbd\xc7\xfb\x4c\x35\x35\x35\xb7\ 203 | \xdf\x7e\xfb\xe6\xcd\x9b\x1f\x79\xe4\x91\x70\x78\x9c\x67\x6a\xec\ 204 | \xdc\xb9\xd3\xe1\x7d\x05\xb2\x41\xef\x2d\x12\x79\x03\x6b\xfb\xf6\ 205 | \xed\x39\x5e\xd5\x75\xfd\xde\x7b\xef\x7d\xe4\x91\x47\x66\xcd\x9a\ 206 | \xe5\xcc\x9d\x65\x8c\xb1\xea\xea\xea\x07\x1e\x78\xe0\xa1\x87\x1e\ 207 | \xf2\x78\x3c\x39\xde\xb9\x65\xcb\x16\x87\xf7\x15\xc8\x06\xbd\xb7\ 208 | \x48\xe4\x0d\xac\xdd\xbb\x77\xe7\x78\xb5\xa9\xa9\xe9\x9e\x7b\xee\ 209 | \xc9\xbd\xeb\x8b\xc1\xe3\xf1\xdc\x79\xe7\x9d\x2b\x57\xae\xcc\xf1\ 210 | \x9e\x96\x96\x16\x87\x5b\x05\xb2\x41\xef\x2d\x12\x79\x03\x6b\xff\ 211 | \xfe\xfd\x63\xbd\x14\x0e\x87\xd7\xae\x5d\x3b\x73\xe6\x4c\x57\x1a\ 212 | \x56\x5d\x5d\xbd\x66\xcd\x9a\xe9\xd3\xa7\x8f\xf5\x86\x63\xc7\x8e\ 213 | \xb9\xd2\x30\x90\x07\x7a\x6f\x91\xc8\x1b\x58\xfd\xfd\xfd\x63\xbd\ 214 | \xb4\x64\xc9\x92\x15\x2b\x56\xb8\xd8\xb6\xab\xae\xba\x6a\xc9\x92\ 215 | \x25\x2e\x36\x00\x24\x87\xde\x5b\x24\xf2\x06\x56\x8e\x19\x82\x16\ 216 | \x2c\x58\xe0\xd6\x1f\xa8\xac\xca\xca\xca\xc5\x8b\x17\xbb\xd8\x00\ 217 | \x90\x1c\x7a\x6f\x91\xc8\x1b\x58\x39\xc8\xb0\xbb\x97\x2d\x5b\xe6\ 218 | \x76\x13\x40\x49\xe8\xbd\x85\x90\xb7\x0e\x2b\x87\x89\xdc\x50\xda\ 219 | \x9d\xb0\x9a\x0f\xa6\x5e\xfe\x34\xd9\xde\x9b\x39\x38\x30\xa1\x79\ 220 | \xa4\x67\x85\xf5\xba\x0a\xe3\xba\x79\x81\x6b\xe6\x04\x66\x86\xc7\ 221 | \xa9\xfa\xbb\xfc\xf2\xcb\xdd\xde\x0d\xc3\x9c\xac\x0e\xcd\xaf\x19\ 222 | \x4a\x6f\x97\xed\xeb\x42\xef\x2d\x84\x92\x81\x55\x5b\x5b\x9b\xe3\ 223 | \x55\x21\xc4\xef\xf6\x27\xee\x6d\xee\x9b\xec\x62\x8f\xc4\xad\x23\ 224 | \x71\xeb\xaf\x7f\x1f\xfa\xe1\x5f\xfb\x1f\x5e\x56\x76\x77\xc3\x34\ 225 | \x7d\xec\x59\xe9\x8b\x5d\x3b\x03\xa5\x0a\xbd\xb7\x10\x4a\x9e\x12\ 226 | \x46\x22\x91\x1c\xaf\xe6\x77\xbc\x47\xf9\xf1\x3b\xb1\x7f\xfb\x20\ 227 | \xd7\x34\xdb\x92\x4c\x2b\x0e\xca\x41\xef\x2d\x84\x92\x81\x95\xe3\ 228 | \x4e\xab\xee\x84\x55\xf8\xf1\xce\xfa\xe9\xfb\xb1\x8e\xfe\x42\x1f\ 229 | \x54\x0b\x30\x0a\x7a\x6f\x21\x94\x0c\xac\x1c\x9a\x0f\xa6\x6c\x5c\ 230 | \xda\xcb\xed\x49\xb7\x37\x08\xa6\x10\xf4\xde\x71\x95\x5a\x60\xbd\ 231 | \xfc\xa9\x9d\x07\x69\xf3\xbe\x41\xb7\x37\x08\xa6\x10\xf4\xde\x71\ 232 | \x95\x5a\x60\xb5\xf7\xda\x39\x0c\x3e\x12\x2f\xec\x31\xb5\x00\x93\ 233 | \x81\xde\x3b\xae\x52\x0b\xac\x09\xfe\x06\x0c\x20\x21\xf4\xde\x71\ 234 | \x95\x5a\x60\x01\x40\x09\x53\xb2\x0e\x4b\x69\xb6\xcf\x7b\xe9\xe4\ 235 | \x54\x9f\xf9\xb5\xd0\x76\xf2\x57\xbd\x42\x91\x60\x84\x05\x00\xca\ 236 | \x40\x60\x01\x80\x32\x10\x58\x00\xa0\x0c\x04\x16\x00\x28\x03\x81\ 237 | \x05\x00\xca\x40\x60\x01\x80\x32\x10\x58\x00\xa0\x0c\x04\x16\x00\ 238 | \x28\x03\x85\xa3\x4e\x93\xa4\xe8\xd1\xc9\xa7\xbd\xdb\x5e\xa4\xea\ 239 | \xe4\x8c\xa3\x20\x15\x8c\xb0\x00\x40\x19\xa5\x16\x58\xb3\xc6\x9b\ 240 | \xcd\x1a\x40\x5a\xe8\xbd\xe3\x2a\xb5\xc0\xaa\xab\xb0\xf3\x24\xb7\ 241 | \x3a\x58\x6a\xfb\x07\x64\x86\xde\x3b\xae\x52\xdb\xa4\xeb\xe6\x05\ 242 | \x6c\x5c\xda\x6d\xf3\x83\x6e\x6f\x10\x4c\x21\xe8\xbd\xe3\x2a\xb5\ 243 | \xc0\xba\x66\x8e\x9d\x87\xfc\xd6\xf9\x21\xb7\x37\x08\xa6\x10\xf4\ 244 | \xde\x71\x29\x19\x58\xa6\x69\x8e\xf5\xd2\xcc\xb0\xfe\xf0\xb2\x32\ 245 | \x5b\xd6\xb2\x66\x61\xe8\xe2\x2a\x8f\xdb\xdb\x0a\xa5\x06\xbd\xb7\ 246 | \x10\x4a\x06\x56\x2c\x16\xcb\xf1\xea\xdd\x0d\xd3\xfe\xf9\x8a\x42\ 247 | \x8f\xfa\x9a\x85\xa1\x47\x9b\xca\x73\xbc\x01\x3f\x9f\x43\x7e\xd0\ 248 | \x7b\x0b\xa1\x64\x1d\x56\x67\x67\x67\x65\x65\xe5\x58\xaf\xea\x1a\ 249 | \xbb\x7f\x49\xd9\x4d\x17\x06\x5e\x6e\x4f\x6e\xde\x37\x38\xa9\x99\ 250 | \xad\xab\x83\xda\x6d\xf3\x83\xb7\xce\x1f\xff\xaf\x53\x77\x77\xb7\ 251 | \xdb\xbb\x01\x94\x84\xde\x5b\x08\x25\x03\xab\xad\xad\xad\xb1\xb1\ 252 | \x31\xf7\x7b\x6a\xcb\x3d\xf7\x5d\xe1\xb9\xaf\xe0\x3f\x56\x63\x69\ 253 | \x69\x69\xb1\x7d\x99\x92\x4c\x46\xea\x24\x27\x1b\x2f\xc9\x26\x97\ 254 | \x6a\xef\x75\x86\x92\xa7\x84\xad\xad\xad\x6e\x37\x81\x76\xec\xd8\ 255 | \xe1\x76\x13\x40\x49\xe8\xbd\x85\x90\x37\xb0\x42\xa1\x31\x7f\xe3\ 256 | \xd8\xbb\x77\x6f\x57\x57\x97\x8b\x6d\x8b\x46\xa3\x32\x74\x3b\x90\ 257 | \x16\x7a\x6f\x91\x14\x31\xb0\x0a\xbc\x7f\xac\xa2\xa2\x62\xac\x97\ 258 | \xde\x7f\xff\xfd\xad\x5b\xb7\x16\xaf\xe5\xe3\xda\xb6\x6d\xdb\x7b\ 259 | \xef\xbd\xe7\x62\x03\x40\x72\x53\xb9\xf7\xda\x7c\xe3\xe8\xe9\x0a\ 260 | \x0a\x2c\x53\x90\x35\x24\x12\x49\xde\x97\x3a\xed\x9f\xe8\x90\xe0\ 261 | \x29\x9e\xcc\x14\x74\xc9\xa0\xae\xae\x6e\xac\x97\xa2\xd1\xe8\xc6\ 262 | \x8d\x1b\x8f\x1f\x3f\x5e\xcc\x3d\x33\xa6\xbe\xbe\xbe\x4d\x9b\x36\ 263 | \xe5\x58\x7b\x55\x55\x95\x2b\x0d\x03\x79\x4c\xe5\xde\x9b\xcc\x08\ 264 | \x9e\xe2\xd1\x21\x31\x2a\x16\x12\x49\x6e\x0d\x09\xb3\xb0\x0b\x89\ 265 | \x05\x5d\x74\xf7\xe9\xec\x92\x99\xde\x84\x4e\x65\x81\xd3\xee\x81\ 266 | \xe2\x42\x0c\x0e\x5a\x35\xa1\x82\x6e\x8c\x5a\xb4\x68\x51\x73\x73\ 267 | \xf3\x58\xaf\x36\x37\x37\x3f\xfb\xec\xb3\x0f\x3c\xf0\x80\xc7\xe3\ 268 | \x68\xb1\x89\x69\x9a\xcf\x3d\xf7\xdc\x6b\xaf\xbd\x96\xe3\x3d\xe3\ 269 | \x5e\x52\x85\x92\x37\x95\x7b\x6f\x4d\x48\x5f\x3e\x2f\x10\x0a\xe9\ 270 | \xda\xe9\x3f\x9b\xc4\x92\xd6\x25\x35\x5e\x9f\x5e\xd8\x08\x4c\x14\ 271 | \x80\x73\x7e\x22\x61\x1e\x1e\xc8\x1c\x8b\x9b\x23\xff\x39\x1a\x37\ 272 | \x0f\xc5\x32\x89\x0c\xe7\x9c\xe7\xbd\xf0\xdf\xff\xfe\xf7\xb9\x5b\ 273 | \x1e\x0e\x87\x1f\x7f\xfc\xf1\x9e\x9e\x9e\x42\xd6\x32\x29\xfd\xfd\ 274 | \xfd\x4f\x3e\xf9\x64\x79\x79\x79\xee\x86\x6d\xd8\xb0\x21\xbf\xe5\ 275 | \xdb\x7e\x04\x6d\x3f\xee\x4e\x36\xa3\x48\x9d\xd6\x19\x53\xb0\xf7\ 276 | \x66\x71\xce\x13\x19\x7e\x28\x96\x39\x7a\x7a\x26\x1c\x8b\x9b\x87\ 277 | \x07\x32\x27\x12\x66\x81\xdb\x2b\xef\xb1\xff\xe8\xa3\x8f\xc6\xfd\ 278 | \xae\x7a\xbd\xde\xaf\x7f\xfd\xeb\x7f\xfc\xe3\x1f\x7b\x7a\x7a\x8a\ 279 | \xda\x98\xfe\xfe\xfe\x57\x5e\x79\xe5\x96\x5b\x6e\xf1\xfb\xfd\xe3\ 280 | \xb6\xea\x6f\x7f\xfb\x5b\x7e\x6b\x99\x60\x42\xb9\xf8\x9d\x77\xb2\ 281 | \x19\xb6\x37\xde\x49\x53\xb0\xf7\x3a\x83\x09\x39\x8a\x53\xce\x64\ 282 | \x9a\xe6\x04\x07\xcc\xd3\xa7\x4f\x6f\x6c\x6c\xbc\xec\xb2\xcb\x96\ 283 | \x2d\x5b\x76\xf9\xe5\x97\xcf\x98\x31\xc3\x96\x19\xe3\x84\x10\xdd\ 284 | \xdd\xdd\x2d\x2d\x2d\x3b\x76\xec\x68\x69\x69\xf9\xf0\xc3\x0f\x8f\ 285 | \x1d\x3b\x36\x91\x0f\xc6\xe3\xf1\x1c\x3f\x12\xe5\x20\x7f\x1d\x96\ 286 | \xed\x4f\x99\x76\xb2\xf1\x4e\x9a\x82\xbd\xd7\x21\x6e\x27\x66\x2e\ 287 | \xeb\xd7\xaf\x77\x7b\xf7\x4c\xda\xaa\x55\xab\x72\x6f\x54\x7e\xc7\ 288 | \x02\x9f\x52\xeb\x53\xa5\xda\x7b\x5d\x27\xef\x08\x8b\x88\x0e\x1c\ 289 | \x38\x30\x77\xee\x5c\xb7\x5b\x31\x39\x2d\x2d\x2d\x97\x5d\x76\x59\ 290 | \x8e\x37\xc8\x3f\x48\xc1\xa7\x0a\xff\x14\x95\x68\xef\x75\x9d\xbc\ 291 | \x85\xa3\x44\x34\x67\xce\x9c\xbb\xee\xba\xcb\xed\x56\x4c\xc2\x8a\ 292 | \x15\x2b\x24\x3f\xde\xe0\x18\xf4\xde\x62\x90\x7a\x84\x45\x44\xd1\ 293 | \x68\x74\xdc\xdf\x35\xe4\x71\xe8\xd0\xa1\xd9\xb3\x67\xe7\x7e\x8f\ 294 | \xfc\xa3\x03\x7c\xaa\xf0\x4f\x65\x95\x5e\xef\x75\x9d\xd4\x23\x2c\ 295 | \x22\x8a\x44\x22\xbb\x76\xed\x72\xbb\x15\x13\xd2\xdc\xdc\x2c\xff\ 296 | \xf1\x06\x27\xa1\xf7\xda\xcf\xed\x8b\x68\x13\x22\xff\x51\x6f\x6e\ 297 | \x6e\x9e\xe0\xb6\xe4\x77\x2c\xf0\x29\xb5\x3e\x35\x52\x29\xf5\x5e\ 298 | \xd7\xa9\x11\x58\x42\x88\x9e\x9e\x9e\x3b\xee\xb8\xc3\xed\x23\x7b\ 299 | \x16\x2b\x56\xac\x38\x74\xe8\xd0\x24\xf6\xf8\xd8\xf0\xa9\x92\xf9\ 300 | \xd4\x28\x25\xd3\x7b\x5d\xa7\x4c\x60\x65\xed\xdd\xbb\x77\xf5\xea\ 301 | \xd5\x6e\x1f\xe5\x61\xab\x56\xad\x6a\x69\x69\x99\xf4\x1e\x1f\x1b\ 302 | \x3e\x55\x32\x9f\x3a\xab\x12\xe8\xbd\xae\x93\xfd\xa2\xfb\x58\x76\ 303 | \xee\xdc\xb9\x73\xe7\xce\x2d\x5b\xb6\xb4\xb4\xb4\x4c\xb0\x22\xae\ 304 | \x70\x55\x55\x55\x8d\x8d\x8d\x57\x5f\x7d\x75\x53\x53\xd3\x95\x57\ 305 | \x5e\x99\xdf\x42\xe4\xbf\x60\x8c\x4f\x15\xfe\xa9\xdc\xd4\xed\xbd\ 306 | \xae\x53\x35\xb0\x4a\x92\xed\x8f\x74\xcf\x21\xbf\xe3\x6e\xfb\x77\ 307 | \x3e\xbf\x16\xda\xbe\xa3\x1c\x0e\x2c\xc8\x9b\xec\xbf\x12\x02\x00\ 308 | \x9c\x82\xc0\x02\x00\x65\x20\xb0\x00\x40\x19\x08\x2c\x00\x50\x06\ 309 | \x02\x0b\x00\x94\x81\xc0\x02\x00\x65\x20\xb0\x00\x40\x19\x08\x2c\ 310 | \x00\x50\x86\x92\x8f\xaa\xcf\xc1\xc9\xca\xc6\x1c\x9c\x2c\x44\x74\ 311 | \x72\x81\x92\xb0\xfd\x50\xca\x53\x04\xef\xd8\xba\x14\x2d\x88\xc5\ 312 | \x08\x0b\x00\x94\x81\xc0\x02\x00\x65\x20\xb0\x00\x40\x19\x08\x2c\ 313 | \x00\x50\x06\x02\x0b\x00\x94\x81\xc0\x02\x00\x65\x20\xb0\x00\x40\ 314 | \x19\x08\x2c\x00\x50\x86\xbc\x33\x8e\x4a\x32\x4d\xa5\xd2\x55\x79\ 315 | \xf2\xef\x43\xf9\x17\x98\x1f\x49\x6a\x4a\xf3\x23\x6d\x26\x10\x46\ 316 | \x58\x00\xa0\x10\x04\x16\x00\x28\x03\x81\x05\x00\xca\x40\x60\x01\ 317 | \x80\x32\x10\x58\x00\xa0\x0c\x04\x16\x00\x28\x03\x81\x05\x00\xca\ 318 | \x40\x60\x01\x80\x32\xe4\x9d\x71\x54\x92\x6a\xc3\x52\x2d\x37\x95\ 319 | \xb9\x38\x70\x5c\x92\xcc\x2b\x9b\x43\xa9\xce\xf5\xea\x3a\x8c\xb0\ 320 | \x00\x40\x19\x08\x2c\x00\x50\x06\x02\x0b\x00\x94\x81\xc0\x02\x00\ 321 | \x65\x20\xb0\x00\x40\x19\x08\x2c\x00\x50\x06\x02\x0b\x00\x94\x81\ 322 | \xc0\x02\x00\x65\xc8\x3b\xe3\x68\x9e\xdb\x23\xfd\xec\x8b\xf2\x4f\ 323 | \x46\xea\x64\xd1\xa3\xfc\x05\x96\x78\x54\xbd\x54\x30\xc2\x02\x00\ 324 | \x65\x20\xb0\x00\x40\x19\x08\x2c\x00\x50\x06\x02\x0b\x00\x94\x81\ 325 | \xc0\x02\x00\x65\x20\xb0\x00\x40\x19\x08\x2c\x00\x50\x06\x02\x0b\ 326 | \x00\x94\x21\x6f\xe1\xe8\x14\x9c\x7d\x51\x92\x0a\x40\xa5\x6b\x4a\ 327 | \x6d\xdf\x2e\x49\xfa\xa1\xd2\x7b\xde\x46\x18\x61\x01\x80\x32\x10\ 328 | \x58\x00\xa0\x0c\x04\x16\x00\x28\x03\x81\x05\x00\xca\x40\x60\x01\ 329 | \x80\x32\x10\x58\x00\xa0\x0c\x04\x16\x00\x28\x03\x81\x05\x00\xca\ 330 | \xc0\xa3\xea\xc7\x21\xc9\xc4\x8c\x4e\x16\x3d\x3a\xb9\xa3\x72\x7c\ 331 | \x4a\x92\xa2\x47\x49\x2a\x36\x25\xe9\x87\xae\xc3\x08\x0b\x00\x94\ 332 | \x81\xc0\x02\x00\x65\x20\xb0\x00\x40\x19\x08\x2c\x00\x50\x06\x02\ 333 | \x0b\x00\x94\x81\xc0\x02\x00\x65\x20\xb0\x00\x40\x19\x08\x2c\x00\ 334 | \x50\x86\x92\x33\x8e\x96\x6a\x2d\x9f\xed\xb5\x97\x92\xec\x28\xdb\ 335 | \xd7\x95\x1f\xf9\x5b\x28\x09\x69\x33\x81\x30\xc2\x02\x00\x85\x20\ 336 | \xb0\x00\x40\x19\x08\x2c\x00\x50\x06\x02\x0b\x00\x94\x81\xc0\x02\ 337 | \x00\x65\x20\xb0\x00\x40\x19\x08\x2c\x00\x50\x06\x02\x0b\x00\x94\ 338 | \x21\x6f\xe1\x28\x8c\x24\xc9\x8c\xa3\x92\xcc\x7b\x69\x7b\x31\xa7\ 339 | \x24\x35\xa5\xf2\xef\x79\xd7\x61\x84\x05\x00\xca\x40\x60\x01\x80\ 340 | \x32\x10\x58\x00\xa0\x0c\x04\x16\x00\x28\x03\x81\x05\x00\xca\x40\ 341 | \x60\x01\x80\x32\x10\x58\x00\xa0\x0c\x04\x16\x00\x28\x63\x72\x8f\ 342 | \xaa\x3f\x18\x33\x3f\x38\x9e\x8e\x78\xb5\x42\x2a\xd5\x18\x51\x3c\ 343 | \xc3\xcb\x7d\x5a\x43\x8d\x37\xe2\xcb\x27\x31\x9d\x9c\x99\x53\x92\ 344 | \xe2\x40\x27\xd7\xe5\x64\x8d\x22\xe6\xf3\x2c\x9c\x2b\x35\xa5\x3d\ 345 | \x49\x6b\x57\x57\x26\x91\x11\x41\x0f\xcb\x6f\x1d\x8c\x28\x96\xe6\ 346 | \xf3\x22\xc6\xc5\x55\x1e\xaf\x3e\xd1\x6e\x30\x89\xc0\x12\x44\x2d\ 347 | \x87\x86\xee\x7e\xf5\x44\x20\xa4\x89\x02\xfa\x19\x63\x94\x4e\xf0\ 348 | \xb9\xd3\x3d\x3f\xbb\xa6\xf2\xcb\x33\x7d\x36\xee\x44\x00\x70\xc6\ 349 | \xfb\xc7\xd2\x3f\xda\xd2\x77\x74\xc0\xf4\xf8\xb5\xfc\x52\x91\x31\ 350 | \x1a\x8a\x5b\xdf\xbc\x74\xda\xfd\x4d\x91\x73\x82\xfa\x04\x3f\x35\ 351 | \x89\xc0\x62\x44\x49\x41\xdd\x44\x61\x53\xe8\x05\x9c\x4a\x32\xa2\ 352 | \xb8\x25\xce\x65\x64\x4c\xbd\xbf\xae\x00\xa5\xc1\xa3\xb1\x24\x51\ 353 | \x8f\x25\x82\x66\x9e\xa3\x38\x46\x14\xb3\x84\xc5\x68\xc2\xa3\x2b\ 354 | \xa2\xc9\x9e\x12\x32\x8d\x34\x9d\x19\x3a\x33\xb4\x82\xb2\x46\x33\ 355 | \x98\xc7\x60\x85\xa4\x1e\x00\xb8\xc8\xd0\xc8\x63\xb0\x6c\x1a\xe4\ 356 | \xbd\x10\xa6\x33\x43\xa3\x49\x7d\xde\xa5\xcc\x98\x42\x77\x6b\x02\ 357 | \x94\x26\x5b\xbe\xc4\x93\x5d\x08\x06\x39\x00\xa0\x0c\x04\x16\x00\ 358 | \x28\x63\x72\xd7\xb0\x46\xca\x7b\x40\xc8\x88\x88\x4d\xee\xc4\x15\ 359 | \x00\x64\x73\xea\x2b\x9c\xf7\x45\xf7\x91\x0b\x99\xa0\xc9\x05\x96\ 360 | \xe0\xc4\x4d\x91\xd1\xc9\x2c\x20\x6f\x18\x91\x95\x11\xa9\x8c\x30\ 361 | \x39\x2e\x65\x01\x28\x29\xc3\x29\x9d\xe1\xa6\x29\x86\xf2\xac\x6a\ 362 | \x20\xc6\x88\x67\x44\xc6\x24\x3e\x99\x4f\x4d\xae\x0e\xab\xdc\x60\ 363 | \x17\x07\x35\x5f\x48\xa3\xc2\x2a\x12\x4c\x2f\x9b\xe1\xd3\xf2\x2e\ 364 | \x1a\xb4\xbd\xf6\xd2\xc9\x87\xb3\x4b\xc2\xc9\xfa\x55\x49\x5a\xa8\ 365 | \xf4\xf1\xca\x4f\xf1\x6a\x4a\x19\xa3\xd9\x01\xdd\x63\x09\x3d\xaf\ 366 | \xda\xef\xac\x8c\xce\x22\x5e\x36\xa9\x11\xda\x24\xa6\x48\x16\x42\ 367 | \x0c\xa4\x45\x57\xc2\xf2\xea\x79\xd6\xb6\x0e\xaf\x92\x28\xc3\xc9\ 368 | \xa7\x53\x75\x50\xf7\x15\xf0\x9b\xe8\xd9\x17\xee\xe0\x97\x4d\x92\ 369 | \xb2\x6f\xa5\x2b\xa7\x25\x99\xfa\xd9\xf6\xc6\xdb\xde\x0c\x49\x66\ 370 | \x85\x3e\x25\x69\x8a\x13\x09\x2b\xc3\xc9\xd0\xf2\x3f\x25\x1c\xb2\ 371 | \x44\xc4\xa7\x55\xf9\x35\x7d\xc2\x65\x52\xa5\x36\xa7\x3b\x02\xab\ 372 | \xa8\xcd\x90\x64\x5d\xf2\xef\x28\xdb\x9b\x21\x5b\x60\xb9\x05\xbf\ 373 | \x12\x02\x80\x32\x10\x58\x00\xa0\x0c\x04\x16\x00\x28\x03\x81\x05\ 374 | \x00\xca\x40\x60\x01\x80\x32\x10\x58\x00\xa0\x8c\xfc\x6f\xcd\x71\ 375 | \x91\x24\x8f\xed\xb6\xbd\x19\x92\x14\x0d\x94\x2a\x27\xf7\x86\x93\ 376 | \x0b\x94\xa4\xd0\xd7\x19\x18\x61\x01\x80\x32\x10\x58\x00\xa0\x0c\ 377 | \x04\x16\x00\x28\x03\x81\x05\x00\xca\x40\x60\x01\x80\x32\x10\x58\ 378 | \x00\xa0\x0c\x04\x16\x00\x28\x03\x81\x05\x00\xca\x90\xb7\x70\x54\ 379 | \x92\x59\x99\x72\x70\x72\x62\xa3\xfc\xea\x06\x6d\xff\x54\x7e\xdb\ 380 | \x35\x05\xab\x28\x9d\x9c\xbe\x2a\xbf\xbd\xa1\x68\x51\x31\x46\x58\ 381 | \x00\xa0\x0c\x04\x16\x00\x28\x03\x81\x05\x00\xca\x40\x60\x01\x80\ 382 | \x32\x10\x58\x00\xa0\x0c\x04\x16\x00\x28\x03\x81\x05\x00\xca\x40\ 383 | \x60\x01\x80\x32\xe4\x2d\x1c\x95\xa4\x38\xd0\xc9\xda\xcb\x1c\x94\ 384 | \x5e\x97\xed\xc7\x4b\x92\x07\xa9\x3a\xb9\x2e\xf9\xa7\xb7\x75\x06\ 385 | \x46\x58\x00\xa0\x0c\x04\x16\x00\x28\x03\x81\x05\x00\xca\x40\x60\ 386 | \x01\x80\x32\x10\x58\x00\xa0\x0c\x04\x16\x00\x28\x03\x81\x05\x00\ 387 | \xca\x40\x60\x01\x80\x32\xe4\x2d\x1c\xb5\x9d\xed\x95\xa8\x4e\x2e\ 388 | \x50\x7e\xb6\xef\x0d\x27\xcb\x83\x15\x9d\x7e\x73\xdc\xc6\x97\xde\ 389 | \x26\x63\x84\x05\x00\xca\x40\x60\x01\x80\x32\x10\x58\x00\xa0\x0c\ 390 | \x04\x16\x00\x28\x03\x81\x05\x00\xca\x40\x60\x01\x80\x32\x10\x58\ 391 | \x00\xa0\x0c\x04\x16\x00\x28\x83\x49\x5b\x24\x26\xc9\xb3\xd4\x95\ 392 | \x7e\xb2\xbc\x24\x9b\x9c\x83\x24\xb3\x9b\x4a\x32\x41\xa8\x93\xb5\ 393 | \xb2\x4e\xee\x0d\x1b\x61\x84\x05\x00\xca\x40\x60\x01\x80\x32\x10\ 394 | \x58\x00\xa0\x0c\x04\x16\x00\x28\x03\x81\x05\x00\xca\x40\x60\x01\ 395 | \x80\x32\x10\x58\x00\xa0\x0c\x04\x16\x00\x28\x43\xde\xc2\xd1\x5c\ 396 | \x8d\xb6\xbb\xbe\xce\xc9\xba\x41\xdb\x9b\xe1\x64\xb5\xa1\x24\xc5\ 397 | \x9c\x4a\x57\xf3\x4a\x42\xd1\xc6\x63\x84\x05\x00\xca\x40\x60\x01\ 398 | \x80\x32\x10\x58\x00\xa0\x0c\x04\x16\x00\x28\x03\x81\x05\x00\xca\ 399 | \x40\x60\x01\x80\x32\x10\x58\x00\xa0\x0c\x04\x16\x00\x28\x43\xde\ 400 | \x47\xd5\x4b\x52\xcb\x27\x7f\x91\xaa\x24\x65\x7e\xf2\xcf\x96\xe9\ 401 | \xe4\x2c\xa0\x92\x54\xf3\x2a\x5a\x1d\x9a\x03\x46\x58\x00\xa0\x0c\ 402 | \x04\x16\x00\x28\x03\x81\x05\x00\xca\x40\x60\x01\x80\x32\x10\x58\ 403 | \x00\xa0\x0c\x04\x16\x00\x28\x03\x81\x05\x00\xca\x40\x60\x01\x80\ 404 | \x32\x94\x9c\x71\x54\x69\xa5\x5a\x52\x28\xc9\x76\xd9\xce\xc9\xda\ 405 | \x4b\x49\x1e\x70\x2f\x73\x26\x60\x84\x05\x00\xca\x40\x60\x01\x80\ 406 | \x32\x10\x58\x00\xa0\x0c\x04\x16\x00\x28\x03\x81\x05\x00\xca\x40\ 407 | \x60\x01\x80\x32\x10\x58\x00\xa0\x0c\x04\x16\x00\x28\x43\xde\x19\ 408 | \x47\x73\xeb\xe8\xe8\x68\x6b\x6b\xdb\xbe\x7d\xfb\xee\xdd\xbb\xf7\ 409 | \xef\xdf\xdf\xdf\xdf\x3f\x30\x30\x50\xbc\xd5\x85\x42\xa1\x8a\x8a\ 410 | \x8a\xba\xba\xba\x45\x8b\x16\x2d\x5f\xbe\xbc\xa1\xa1\x61\xfe\xfc\ 411 | \xf9\xf9\x2d\xca\xc9\x27\xb0\x3b\xc9\xc9\x72\x53\x27\x1f\x55\x9f\ 412 | \x1f\x27\xeb\x72\x9d\xdc\x2e\xf7\x09\xa5\x1c\x39\x72\xe4\xd1\x47\ 413 | \x1f\x75\x7b\x9f\x0d\x5b\xbf\x7e\x7d\x67\x67\xa7\x8d\x5b\xe7\xe4\ 414 | \x11\x94\xa4\x4b\x38\x79\xbc\x9c\xdc\xf3\xf2\x37\x23\xbf\x05\xba\ 415 | \x4e\xea\xc6\x8d\x34\x34\x34\xf4\xf0\xc3\x0f\xdb\xda\x81\xed\x71\ 416 | \xd7\x5d\x77\x45\xa3\x51\x7b\x0e\x86\x83\xdd\x4b\x92\xfe\xea\xe4\ 417 | \x91\x72\x72\xcf\xcb\xdf\x8c\xfc\x16\xe8\x3a\x35\xee\x25\xec\xec\ 418 | \xec\xac\xaf\xaf\x8f\xc7\xe3\x6e\x37\x64\x4c\xbb\x76\xed\x5a\xbc\ 419 | \x78\x71\x81\x0b\x71\xf2\x94\x50\x92\xc7\x13\x48\x72\x07\xa2\x93\ 420 | \xe7\x98\x92\x34\x23\xbf\x05\xba\x4e\x81\x8b\xee\x9d\x9d\x9d\xf3\ 421 | \xe6\xcd\x93\x39\xad\x88\xa8\xa1\xa1\xa1\xb5\xb5\xd5\xed\x56\x00\ 422 | \x94\x38\xd9\x47\x58\xc9\x64\xb2\xa6\xa6\x46\xf2\xb4\x3a\xa5\xa7\ 423 | \xa7\xa7\xb2\xb2\x32\xef\x8f\x63\x84\x55\x54\x92\x0c\x6d\x24\x69\ 424 | \x46\x7e\x0b\x74\x9d\xec\x23\xac\x27\x9e\x78\x42\x95\xb4\x22\xa2\ 425 | \x75\xeb\xd6\xb9\xdd\x04\x80\x52\x26\xf5\x08\xeb\xe8\xd1\xa3\xb3\ 426 | \x66\xcd\x72\xbb\x15\x93\xb3\x77\xef\xde\x05\x0b\x16\xe4\xf7\x59\ 427 | \x8c\xb0\x8a\x4a\x92\xa1\x8d\x24\xcd\xc8\x6f\x81\xae\x93\x7a\x84\ 428 | \xf5\xcc\x33\xcf\xb8\xdd\x84\x49\xdb\xb0\x61\x83\xdb\x4d\x00\x28\ 429 | \x59\xf2\x8e\xb0\x38\xe7\xba\xae\x4f\xe4\x9d\xe1\x70\xf8\x8a\x2b\ 430 | \xae\x58\xb8\x70\x61\x7d\x7d\x7d\x7d\x7d\x7d\x6d\x6d\x6d\x24\x12\ 431 | \x31\x8c\x82\x6a\x62\x4d\xd3\x8c\xc5\x62\x9d\x9d\x9d\x6d\x6d\x6d\ 432 | \xad\xad\xad\x7b\xf6\xec\xf9\xe0\x83\x0f\xa2\xd1\xe8\x44\x3e\x9b\ 433 | \x48\x24\x02\x81\xc0\x58\xaf\x4a\x52\xcb\x27\xff\x30\x6a\x0a\xb6\ 434 | \x50\xfe\xd9\x4d\x5d\x27\x6f\x60\x75\x74\x74\x5c\x70\xc1\x05\xb9\ 435 | \xdf\xa3\xeb\x7a\x53\x53\xd3\xda\xb5\x6b\x57\xae\x5c\x39\x63\xc6\ 436 | \x8c\xe2\x35\xa6\xab\xab\x6b\xeb\xd6\xad\x1b\x37\x6e\x6c\x6e\x6e\ 437 | \xce\x64\x32\xb9\xdf\xfc\xce\x3b\xef\x2c\x5d\xba\x74\xac\x57\x11\ 438 | \x58\x68\x61\x1e\xcd\x50\x7a\x5d\x36\x92\xf7\x94\xb0\xad\xad\x2d\ 439 | \xf7\x1b\x02\x81\xc0\x83\x0f\x3e\xf8\xfc\xf3\xcf\xaf\x5e\xbd\xba\ 440 | \xa8\x69\x45\x44\x35\x35\x35\xb7\xdf\x7e\xfb\xe6\xcd\x9b\x1f\x79\ 441 | \xe4\x91\x70\x38\x9c\xfb\xcd\x3b\x77\xee\x74\x78\x5f\x01\x4c\x11\ 442 | \x05\x05\x96\x10\x22\xc3\xc5\x90\x25\xd2\x67\xfc\x33\x64\x09\x5e\ 443 | \x40\xad\x2d\x11\x6d\xdf\xbe\x3d\xc7\xab\xba\xae\xdf\x7b\xef\xbd\ 444 | \x8f\x3c\xf2\xc8\xac\x59\xb3\x9c\x19\xb3\x30\xc6\xaa\xab\xab\x1f\ 445 | \x78\xe0\x81\x87\x1e\x7a\xc8\xe3\xf1\xe4\x78\xe7\x96\x2d\x5b\x1c\ 446 | \x68\x0f\x80\x84\x84\x10\x5c\x8c\x99\x09\x19\x5e\x50\x26\x50\x81\ 447 | \x37\x3f\x67\x38\x6d\xff\x3c\x75\x70\xc0\xf2\x18\xa3\x4f\x2d\x2d\ 448 | \x53\x5c\x39\xc7\x3f\x37\x92\xff\xf2\x77\xef\xde\x9d\xe3\xd5\xa6\ 449 | \xa6\xa6\x7b\xee\xb9\x27\x77\x70\x14\x83\xc7\xe3\xb9\xf3\xce\x3b\ 450 | \x77\xec\xd8\xf1\xfa\xeb\xaf\x8f\xf5\x9e\x96\x96\x16\x87\x5b\x05\ 451 | \x20\x8f\x03\x51\xf3\xed\x03\x29\xdd\x38\x6d\x18\xc1\x18\xcb\x98\ 452 | \xe2\xbc\x69\x7a\xd3\xf9\x7e\xef\x84\x2e\x4d\x9f\x5d\x41\x81\x95\ 453 | \x30\xc5\xbf\x6f\x8f\xbe\xd4\x91\x30\xfc\xfa\x69\x81\x25\x28\x98\ 454 | \xb2\x7e\x79\xfb\x8c\xf3\x23\x46\xde\x6d\xdb\xbf\x7f\xff\x58\x2f\ 455 | \x85\xc3\xe1\xb5\x6b\xd7\xce\x9c\x39\xb3\x90\xc6\xe7\xad\xba\xba\ 456 | \x7a\xcd\x9a\x35\xef\xbe\xfb\xee\x89\x13\x27\xce\xfa\x86\x63\xc7\ 457 | \x8e\xb9\xd2\x30\x00\xd7\x71\xa2\x9d\x47\xd2\xff\xf3\x4f\x5d\x09\ 458 | \xbf\x4e\x23\x22\x8b\x31\x66\xa6\xac\x1b\x6b\x83\x97\xce\xf6\x79\ 459 | \xf5\xfc\x4f\x89\x0a\x0a\x2c\x83\x91\x1e\xd4\x42\x65\x46\xd0\x77\ 460 | \xda\xa9\x25\x17\xc2\xf2\xb2\x88\xaf\xa0\x53\xb5\xfe\xfe\xfe\xb1\ 461 | \x5e\x5a\xb2\x64\xc9\x8a\x15\x2b\x0a\x69\x79\x81\xae\xba\xea\xaa\ 462 | \x25\x4b\x96\xbc\xf1\xc6\x1b\x2e\xb6\x01\x40\x42\x8c\x28\xe2\x63\ 463 | \x7a\x99\x51\xee\xd7\xb4\xd3\x03\x20\xe1\x65\x7a\x50\x33\x0a\xbb\ 464 | \x7e\x53\x9c\x8b\xee\xe2\xd4\x7f\xe5\x2f\xc7\xfc\x56\x0b\x16\x2c\ 465 | \x70\x6b\x78\x95\x55\x59\x59\x59\xf8\xad\xce\x00\x25\x49\x9c\xf6\ 466 | \x3f\x36\x93\xf7\x57\xc2\x1c\x64\x08\x8b\x65\xcb\x96\xb9\xdd\x04\ 467 | \x80\x29\x47\xc9\x19\x47\xeb\xeb\xeb\xc7\x7d\x4f\x77\xc2\x6a\x3e\ 468 | \x98\x7a\xf9\xd3\x64\x7b\x6f\xe6\xe0\x80\x35\x91\xc5\xce\x0a\xeb\ 469 | \x75\x15\xc6\x75\xf3\x02\xd7\xcc\x09\xcc\x0c\x8f\x73\xf1\xed\xf2\ 470 | \xcb\x2f\xb7\x7d\xbb\x9c\xbc\xc9\xc6\xc9\x4f\xd9\xbe\x5d\x39\xe4\ 471 | \xb7\xae\xfc\x36\xd9\xc9\x92\x3a\x27\x8f\x97\xcc\x94\x0c\xac\xda\ 472 | \xda\xda\x1c\xaf\x0a\x21\x7e\xb7\x3f\x71\x6f\x73\xdf\x64\x17\x7b\ 473 | \x24\x6e\x1d\x89\x5b\x7f\xfd\xfb\xd0\x0f\xff\xda\xff\xf0\xb2\xb2\ 474 | \xbb\x1b\xa6\xe9\xda\x98\xc7\xbb\xd8\x95\x5f\x00\x70\x26\x25\x4f\ 475 | \x09\x23\x91\x48\x8e\x57\xf3\x4b\xab\x51\x7e\xfc\x4e\xec\xdf\x3e\ 476 | \xc8\x35\x49\xbc\x24\x05\xeb\x00\x53\x8a\x92\x81\x95\xe3\x3e\xc1\ 477 | \xee\x84\x55\x78\x5a\x65\xfd\xf4\xfd\x58\x47\x7f\xa6\xf0\xe5\x00\ 478 | \x80\x5d\x94\x0c\xac\x1c\x9a\x0f\xa6\x6c\x5c\xda\xcb\xed\x49\xb7\ 479 | \x37\x08\x00\xbe\x50\x6a\x81\xf5\xf2\xa7\x76\x46\xcc\xe6\x7d\x83\ 480 | \x6e\x6f\x10\x00\x7c\xa1\xd4\x02\xab\xbd\xd7\xce\x93\xb8\x23\xf1\ 481 | \x09\xfd\xbc\x08\x00\xce\x28\xb5\xc0\x9a\x60\x05\x03\x00\xa8\xa8\ 482 | \xd4\x02\x0b\x00\x4a\x98\x92\x75\x58\x4a\xb3\xbd\x60\x4f\x92\x0a\ 483 | \x40\xa5\x2b\x1b\x95\x9e\xc0\x4f\x92\x7d\xe8\x0c\x8c\xb0\x00\x40\ 484 | \x19\x08\x2c\x00\x50\x06\x02\x0b\x00\x94\x81\xc0\x02\x00\x65\x20\ 485 | \xb0\x00\x40\x19\x08\x2c\x00\x50\x06\x02\x0b\x00\x94\x81\xc0\x02\ 486 | \x00\x65\xa0\x70\xd4\x69\x92\x14\x07\x3a\xf9\x29\xf9\x2b\x1b\x6d\ 487 | \x9f\x71\x34\xbf\x05\xda\xde\xf8\x1c\xe4\x3f\x28\x67\x85\x11\x16\ 488 | \x00\x28\xa3\xd4\x02\x6b\xd6\x78\x73\xb1\x03\x80\xba\x4a\x2d\xb0\ 489 | \xea\x2a\xec\x3c\xc9\xad\x0e\x96\xda\xfe\x01\x50\x5a\xa9\x7d\x21\ 490 | \xaf\x9b\x17\xb0\x71\x69\xb7\xcd\x0f\xba\xbd\x41\x00\xf0\x85\x52\ 491 | \x0b\xac\x6b\xe6\xd8\x19\x58\xb7\xce\x0f\xb9\xbd\x41\x00\xf0\x05\ 492 | \x25\x03\xcb\x34\xcd\xb1\x5e\x9a\x19\xd6\x1f\x5e\x56\x66\xcb\x5a\ 493 | \xd6\x2c\x0c\x5d\x5c\xe5\x71\x7b\x5b\x01\xe0\x0b\x4a\x06\x56\x2c\ 494 | \x16\xcb\xf1\xea\xdd\x0d\xd3\xfe\xf9\x8a\x42\x33\x6b\xcd\xc2\xd0\ 495 | \xa3\x4d\xe5\x39\xde\x20\xf3\x4f\xbf\x00\xa5\x4a\xc9\x3a\xac\xce\ 496 | \xce\xce\xca\xca\xca\xb1\x5e\xd5\x35\x76\xff\x92\xb2\x9b\x2e\x0c\ 497 | \xbc\xdc\x9e\xdc\xbc\x6f\x70\x52\xf3\xb2\x57\x07\xb5\xdb\xe6\x07\ 498 | \x6f\x9d\x3f\xfe\xd8\xaa\xbb\xbb\xdb\xed\xdd\x00\x30\xe5\x28\x19\ 499 | \x58\x6d\x6d\x6d\x8d\x8d\x8d\xb9\xdf\x53\x5b\xee\xb9\xef\x0a\xcf\ 500 | \x7d\x05\x0f\xb5\xc6\xd2\xd2\xd2\x92\xdf\x07\x9d\x7c\x96\xba\x24\ 501 | \x0b\xcc\xc1\xc9\xda\x4b\x49\x36\xd9\xf6\x05\x4a\xd2\x78\x67\x28\ 502 | \x79\x4a\xd8\xda\xda\xea\x76\x13\x68\xc7\x8e\x1d\x6e\x37\x01\x60\ 503 | \xca\x91\x37\xb0\x42\xa1\x31\x7f\xa1\xdb\xbb\x77\x6f\x57\x57\x97\ 504 | \x8b\x6d\x8b\x46\xa3\x32\x84\x26\xc0\x54\x23\x6f\x60\x55\x54\x54\ 505 | \x8c\xf5\xd2\xfb\xef\xbf\xbf\x75\xeb\x56\x17\xdb\xb6\x6d\xdb\xb6\ 506 | \xf7\xde\x7b\xcf\xc5\x06\x00\x4c\x4d\xf2\x06\x56\x5d\x5d\xdd\x58\ 507 | \x2f\x45\xa3\xd1\x8d\x1b\x37\x1e\x3f\x7e\xdc\x95\x86\xf5\xf5\xf5\ 508 | \x6d\xda\xb4\x29\xc7\xda\xab\xaa\xaa\x5c\x69\x18\x40\xc9\x93\x37\ 509 | \xb0\x16\x2d\x5a\x94\xe3\xd5\xe6\xe6\xe6\x67\x9f\x7d\x36\x93\xb1\ 510 | \xf3\x39\xcf\x13\x61\x9a\xe6\x73\xcf\x3d\xf7\xda\x6b\xaf\xe5\x78\ 511 | \xcf\xb8\x3f\x08\x00\x40\x7e\xe4\x0d\xac\xe5\xcb\x97\xe7\x78\x35\ 512 | \x93\xc9\x6c\xd8\xb0\xe1\xc9\x27\x9f\xec\xed\xed\x75\xec\xf7\x8e\ 513 | \x68\x34\xfa\xf3\x9f\xff\xfc\xf1\xc7\x1f\x4f\xa5\x52\x39\xde\x76\ 514 | \xf5\xd5\x57\x3b\xb9\xa3\x00\xa6\x0e\x79\xcb\x1a\x1a\x1a\x1a\x72\ 515 | \xbf\x21\x1e\x8f\x3f\xf6\xd8\x63\x3b\x76\xec\x58\xb3\x66\xcd\x55\ 516 | \x57\x5d\x95\xa3\x32\xab\x70\xd1\x68\x74\xdb\xb6\x6d\x9b\x36\x6d\ 517 | \x7a\xed\xb5\xd7\x72\xa7\x15\x11\x35\x35\x35\x39\xbe\xb7\x00\xa6\ 518 | \x04\x79\x03\xab\xb6\xb6\x76\xdc\xf7\xa4\xd3\xe9\xd7\x5f\x7f\xfd\ 519 | \xdd\x77\xdf\x6d\x6c\x6c\xbc\xec\xb2\xcb\x96\x2d\x5b\x76\xf9\xe5\ 520 | \x97\xcf\x98\x31\xc3\x96\x39\xd2\x84\x10\xdd\xdd\xdd\x2d\x2d\x2d\ 521 | \x3b\x76\xec\x68\x69\x69\xf9\xf0\xc3\x0f\x8f\x1d\x3b\x36\x91\x0f\ 522 | \x5e\x7a\xe9\xa5\x6e\xef\x3c\x80\xd2\x24\x6f\x60\x19\x86\xb1\x7e\ 523 | \xfd\xfa\xa7\x9e\x7a\x6a\xdc\x77\x9e\x38\x71\xe2\xad\xb7\xde\x7a\ 524 | \xeb\xad\xb7\xdc\x6e\x32\x11\xd1\xaa\x55\xab\x72\x14\x64\xe4\x26\ 525 | \xff\x24\x90\x4e\x4e\xa4\x99\x5f\x33\x72\xb0\xbd\x85\x4e\x2e\xd0\ 526 | \xf6\x0e\x20\x7f\x67\x3b\x2b\x79\xaf\x61\x11\xd1\xba\x75\xeb\xdc\ 527 | \x6e\xc2\xa4\x3d\xf6\xd8\x63\x6e\x37\x01\xa0\x64\x49\x1d\x58\x73\ 528 | \xe6\xcc\xb9\xeb\xae\xbb\xdc\x6e\xc5\x24\xac\x58\xb1\xe2\xb2\xcb\ 529 | \x2e\x73\xbb\x15\x00\x25\x4b\xea\xc0\x22\xa2\x9f\xfc\xe4\x27\x6e\ 530 | \x37\x61\x12\x7e\xf3\x9b\xdf\xb8\xdd\x04\x80\x52\x26\x7b\x60\x45\ 531 | \x22\x91\x5d\xbb\x76\xb9\xdd\x8a\x09\x69\x6e\x6e\x9e\x3d\x7b\xb6\ 532 | \xdb\xad\x00\x28\x65\xb2\x07\x16\x11\x2d\x5e\xbc\x58\xfe\xcc\x6a\ 533 | \x6e\x6e\xfe\xea\x57\xbf\xea\x76\x2b\x00\x4a\x9c\x02\x81\x45\x44\ 534 | \x8b\x17\x2f\xee\xe9\xe9\xb9\xe3\x8e\x3b\xdc\x6e\xc8\x59\xac\x58\ 535 | \xb1\xe2\xd0\xa1\x43\x48\x2b\x00\x07\xa8\x11\x58\x44\x54\x59\x59\ 536 | \xb9\x79\xf3\xe6\xbd\x7b\xf7\xae\x5e\xbd\xda\xed\xb6\x0c\x5b\xb5\ 537 | \x6a\x55\x4b\x4b\xcb\x5f\xfe\xf2\x17\x9c\x09\x02\x38\xa3\x88\x75\ 538 | \x58\x5a\x11\x0a\x73\x16\x2c\x58\xb0\x69\xd3\xa6\x4d\x9b\x36\xed\ 539 | \xdc\xb9\x73\xe7\xce\x9d\x5b\xb6\x6c\x69\x69\x69\x99\x60\x3d\x67\ 540 | \xe1\xaa\xaa\xaa\x1a\x1b\x1b\xaf\xbe\xfa\xea\xa6\xa6\xa6\x2b\xaf\ 541 | \xbc\xd2\x99\x95\x02\xa8\xa5\x18\x5f\xfc\x53\x8a\x18\x58\x45\x2d\ 542 | \x3f\x5b\xba\x74\xe9\xd2\xa5\x4b\x7f\xf0\x83\x1f\x14\x6f\x15\xce\ 543 | \x73\xf2\xf1\xf1\xf2\x37\xc3\x76\xf2\xb7\xb0\x34\xb6\xab\xa8\xed\ 544 | \x29\xe8\x94\x90\x31\x1a\x2b\x4c\x05\x91\xc9\x8b\xb9\x57\x00\x40\ 545 | \x4a\x26\xa7\xb1\x12\x2b\x47\x62\x4c\x50\x41\x81\xa5\x6b\x4c\xd3\ 546 | \x98\xa0\xb3\xb4\x4f\x10\xc5\xd2\x5c\xae\xe4\x07\x80\x22\x1b\xeb\ 547 | \x8b\x9f\x4d\x09\x4d\x67\x7a\x61\x89\x55\x50\x60\xf9\x34\xf2\x7a\ 548 | \x18\x3f\x73\x10\xc8\xc8\x62\xec\x60\xcc\x22\x24\x16\xc0\x94\x22\ 549 | \xe8\x60\xcc\xb2\x18\xa3\xd3\x73\x49\x08\xc1\x89\xbc\x06\xf3\xea\ 550 | \x05\x2d\xbe\xc0\x53\x42\x56\xee\xd7\x74\x8d\xce\x92\xa8\x3a\xed\ 551 | \x39\x91\xe1\x82\x24\x3b\xbf\x06\x80\x62\x11\x82\xb8\xa0\x3d\x27\ 552 | \x32\x74\x46\x2a\x71\x41\xba\x46\x11\xbf\x56\xe0\x25\xf9\x42\xcb\ 553 | \x1a\xe6\x95\x1b\x01\x43\xe3\xa3\x07\x58\xa4\x33\x6a\x39\x36\x14\ 554 | \xcf\x9c\xf5\x7c\x11\x00\x4a\x92\x88\x67\x44\xcb\xb1\x21\x7d\xf4\ 555 | \x00\x8b\xb8\xa0\x80\xa1\xd5\x96\x17\xfa\x2b\x5f\xa1\x81\x55\x57\ 556 | \xe1\xa9\xf4\x32\x7e\x7a\x62\x31\xc6\x0c\x8d\xc5\x07\xad\xcf\xfa\ 557 | \xcd\x7c\x17\x0c\x00\xea\xf9\xac\xdf\x8c\x0f\x5a\x86\xc6\x46\x4d\ 558 | \x5f\xc3\xb9\xa8\xf4\xb2\xba\x0a\x4f\xbe\x0b\x1e\x56\x68\x60\x5d\ 559 | \x58\x69\xd4\xf8\x35\x71\xb6\x1f\x04\x13\x9c\xde\xe8\x4c\x3a\xba\ 560 | \xb7\x00\xc0\x55\x6f\x74\x26\x13\x67\x4b\x03\xc1\xa9\xc6\xaf\x5d\ 561 | \x58\xe9\xf6\x08\xeb\xbc\x69\xc6\x39\xd3\x74\xce\x46\x5f\xab\xd2\ 562 | \x18\x09\x9d\xbd\xf4\x51\xa2\x7f\x08\xa7\x84\x00\x53\x42\xff\x90\ 563 | \x78\xe9\xa3\x84\xd0\x99\x36\xfa\x8a\x3b\x71\x46\xe7\x4c\xd3\xcf\ 564 | \x9b\xe6\x76\x60\x79\x75\xb6\xe8\x1c\x9f\x57\x63\x16\x17\xd9\x96\ 565 | \x11\x91\x20\x62\x8c\x79\x35\x3a\xdc\x9f\x79\xe5\xd3\x84\x7b\x3b\ 566 | \x10\x00\x9c\xf3\xca\xa7\x89\xc3\xfd\x19\xaf\x46\x8c\xb1\xec\x38\ 567 | \x25\x1b\x08\x16\x17\x5e\x8d\x2d\x3a\xc7\xe7\xd5\x0b\x2d\x82\xb7\ 568 | \xe1\x5e\xc2\x15\x73\xfc\xb3\x03\xda\xc8\xcb\x58\xec\xe4\xff\x0c\ 569 | \x32\x7a\x6e\x57\xbc\x2f\x85\x12\x52\x80\x12\xd7\x97\xe2\xcf\xed\ 570 | \x8a\x27\x4f\x5e\xbc\x1a\x99\x4c\x9c\x8b\xd9\x01\x6d\xc5\x1c\x7f\ 571 | \xe1\x6b\xb1\x21\xb0\x1a\x6a\xbc\xf3\x2a\x0c\x53\x10\x17\xe2\xd4\ 572 | \x85\x36\x21\x48\x63\x2c\xa0\xb3\x8f\xba\xd3\xbf\x6e\x8b\x3b\xbf\ 573 | \xfb\x00\xc0\x49\xbf\x6e\x8b\x7f\xd4\x9d\xf6\xea\xc4\x18\x3b\x75\ 574 | \x81\x88\x31\xe2\x42\x98\x82\xe6\x55\x18\x0d\x35\xde\xc2\xd7\x62\ 575 | \x43\x60\x05\x0c\x76\x6d\x5d\x30\xac\x33\xce\x89\x4e\x0e\x02\x87\ 576 | \x53\x96\x51\x8a\xd1\xaf\x3e\x1c\xd8\x71\x78\xc8\xa5\xdd\x08\x00\ 577 | \x45\xb7\xe3\xf0\xd0\xaf\x3e\x1c\x48\x31\xd2\x4e\x7e\xf1\xe9\x64\ 578 | \x14\x70\x4e\x61\x9d\x5d\x5b\x17\x0c\x18\x36\xdc\x14\x6d\xcf\xf4\ 579 | \x32\x37\x5f\x18\x9c\x53\x66\x64\xb8\x10\xa7\x0f\xb2\x18\x63\x7e\ 580 | \x83\x1d\x1e\xb4\xfe\x75\x47\xf4\x60\x0c\x25\x0e\x00\x25\xe8\x60\ 581 | \xcc\xfc\xd7\x1d\xd1\xc3\x83\x96\xdf\x60\xa3\x86\x57\x42\x88\x0c\ 582 | \x17\x73\xca\x8c\x9b\x2f\x0c\xda\xb2\x2e\x7b\x02\xab\x26\xa8\xdf\ 583 | \xb6\x30\xe4\x27\x96\xbd\x90\x75\x6a\x90\x95\xcd\x2c\x9f\xc1\xb6\ 584 | \xff\x3d\xf5\xd4\xbb\xb1\x13\x49\xcb\x85\xdd\x09\x00\x45\x73\x22\ 585 | \x69\x3d\xf5\x6e\x6c\xfb\xdf\x53\xbe\x93\x69\x75\xda\xf0\x4a\x90\ 586 | \x9f\xd8\x6d\x0b\x43\x35\xc1\xc2\x6e\xc9\x39\xc9\xb6\x09\xfc\xbe\ 587 | \x7d\x49\xa8\xae\xd2\x48\x64\x86\x07\x59\xd9\x90\xcd\x46\xac\xae\ 588 | \x33\x61\xb0\xdf\xed\x8d\xff\x7c\x27\x32\x0b\xa0\x74\x9c\x48\x5a\ 589 | \x3f\xdf\x19\xfb\xdd\xde\xb8\x30\x98\xae\xb3\x53\x27\x58\xe2\xe4\ 590 | \x77\x3f\x91\x11\x75\x95\xc6\xb7\x2f\xc9\xf3\x49\x9d\x67\xb2\x2d\ 591 | \xb0\xaa\x02\xfa\x7d\x4b\x23\x11\x46\x56\xf6\x27\xc1\xd3\x7f\x33\ 592 | \x34\x74\x4a\x33\x7a\xb6\x75\xe0\xf1\xb7\xa3\x07\x70\x6e\x08\xa0\ 593 | \xbe\x03\x31\xf3\xf1\xb7\xa3\xcf\xb6\x0e\xa4\x19\x19\xc3\xe3\xa7\ 594 | \x53\xd7\x83\x88\x88\x2c\x4e\x11\x46\xf7\x2d\x8d\x54\x05\xec\x19\ 595 | \x5e\x91\xbd\x53\x24\x7f\xbd\x36\x70\xf3\x82\x90\x39\xc4\x47\x5e\ 596 | \xc9\x62\xc3\x35\xa5\xcc\x6b\xb0\x8c\xc6\x36\xef\x89\x7f\xff\xad\ 597 | \xde\xb7\x0f\xa5\x8a\xbf\x3f\x01\xa0\x58\xde\x3e\x94\xfa\xfe\x5b\ 598 | \xbd\x9b\xf7\xc4\x33\x1a\xf3\x1a\x8c\xe8\x8b\x93\x41\x3a\x39\xbc\ 599 | \x32\x87\xf8\xcd\x0b\x42\x5f\xaf\x0d\xd8\xb8\x5e\x66\xe3\xf4\x80\ 600 | \x42\x88\xcf\x63\xd6\xf5\x2f\x74\xb5\xf7\x67\x22\x01\x6d\x64\x29\ 601 | \xc6\xa9\x8d\xb1\xb8\x48\xa7\xf9\xf4\xa0\x7e\x4f\x63\xd9\x77\x16\ 602 | \x85\x6c\x8c\x5e\x00\x70\x40\x4f\xd2\xda\xb8\x7b\xf0\x3f\x5a\x62\ 603 | \x27\x12\x96\xd7\xab\xe9\x1a\xa3\x11\x5f\xf0\x93\x44\x34\xc9\xeb\ 604 | \xca\x3d\xaf\xde\x5a\x73\x7e\x99\xce\xec\x9b\x34\xd9\xce\xc0\x22\ 605 | \x22\x2e\xc4\x3b\x87\x87\xbe\xf1\x87\xae\x21\x8d\x05\x3d\x34\x2a\ 606 | \xb3\x88\x04\x63\x4c\x08\x91\x34\x45\x90\xe8\xc2\x2a\xef\xf7\x2e\ 607 | \x0d\x5f\x5f\x1b\xa8\xf0\x9f\x1a\xe8\xd9\xb8\x69\x00\x50\xa8\xec\ 608 | \xd7\x36\xfb\xff\xfb\x52\xfc\xd5\x8e\xe4\xb3\x1f\xc6\x3f\xe9\x49\ 609 | \x27\x88\x02\xc3\x57\xd9\xc5\x19\x5f\x5b\x91\xc8\x90\x8f\x8b\x3f\ 610 | \xdf\x56\xb3\x6c\xb6\xcf\xde\x29\xde\x6d\x0e\x2c\x22\x32\xb9\x78\ 611 | \xe3\xd3\xe4\x77\xfe\xdc\x6d\x79\x35\xbf\x41\xa7\x97\xbc\x0e\x27\ 612 | \xb1\x10\x42\x08\x4a\x9a\x22\xc4\x68\x76\xc4\x73\xe3\xfc\xe0\xb5\ 613 | \x73\xfd\xb5\x15\x46\xd8\xa3\x69\x8c\xce\x98\xfc\x4b\x2e\xd9\xb6\ 614 | \x21\x59\xa1\x70\x42\xb6\xf9\xd8\x47\xb6\xed\xe4\xfc\x56\xf1\x0c\ 615 | \xef\xe8\x33\xdf\xec\x4c\xbd\xf4\x71\xe2\x70\x34\x33\x28\xb2\x51\ 616 | \x45\x23\x7f\x13\x1c\xf9\xb9\x94\x49\x7a\x9a\x3f\x77\x43\xf5\xf5\ 617 | \x75\x01\x43\xb3\xf9\x6b\x62\x7f\x60\x09\x21\x86\x2c\x7a\x61\xff\ 618 | \xe0\xba\x37\x7b\xf8\xd8\x99\x45\x44\x5c\x08\x12\x94\xe6\xc4\x2c\ 619 | \x11\xd0\x58\x38\xa4\x2d\xae\xf1\xce\xaf\xf4\xcc\xaf\x30\x22\x3e\ 620 | \x4d\x97\xef\x09\x64\x8c\x28\x99\x11\x17\x4f\xf7\xcc\xaf\xf4\xd8\ 621 | \x7e\x24\x60\x0a\x1a\xb2\xc4\xfe\x13\x99\xf6\xbe\x4c\xd0\xc3\xa4\ 622 | \x4a\x2e\x8b\x53\x74\x88\x7f\xdc\x67\x7e\xdc\x9b\x69\xed\x4a\xc7\ 623 | \x07\x79\x92\x0b\xa1\x33\xaf\x46\xc4\x86\x9f\x8b\x33\x56\x5a\x69\ 624 | \x69\xfe\xf4\xb5\x55\xb7\x5c\x1c\xf2\xeb\xf6\xff\x5d\xb7\x3f\xb0\ 625 | \x88\x48\x08\x91\x30\xc5\x9f\x3e\x4a\xac\x7b\xb3\x27\x6d\xb0\xb0\ 626 | \x77\xf8\x9a\x1c\x8d\x18\x3a\x8d\xa8\xd7\x10\xd9\xea\x2d\x93\x93\ 627 | \x29\x04\x09\x66\x58\x82\x91\x90\x33\x0f\x78\xcc\xfa\xde\x7f\x2b\ 628 | \xff\xd1\x57\xca\x23\x3e\xf9\x02\x15\x54\x73\x6c\xd0\xfa\x5f\xff\ 629 | \xb7\xef\xf7\xef\xc7\x8c\x32\xb9\x2e\xe6\x0a\x22\x41\xcc\xd4\x19\ 630 | \x31\x61\x30\x66\x68\x44\x44\x1a\x1b\x0e\xa0\x91\x51\x95\x3d\x65\ 631 | \xcc\xfe\xeb\x78\x5a\x78\x4d\xf1\xf4\xb5\x55\x37\x5d\x14\x0c\x1a\ 632 | \xac\x18\x67\x21\x45\x79\xcc\x17\x63\x2c\x68\xd0\x2d\x17\x87\x42\ 633 | \x5e\xed\xce\x37\x4e\x44\x93\xbc\xcc\xaf\x8d\xda\xd4\x11\xf5\x1a\ 634 | \x2c\x7b\x0b\xb7\xc6\x84\x27\x1b\x68\x06\x23\x59\x4f\x0a\x07\xfc\ 635 | \x22\x12\xd4\x0a\xbe\xe7\x1c\x80\x88\xc8\xa3\xd1\xb4\xa0\x96\x0c\ 636 | \x68\x15\x7e\x4d\xc2\x93\x43\x0f\xa3\xec\x37\xf5\x54\xf4\x08\x22\ 637 | \x46\x74\xfa\xdd\x2c\x44\x8c\x84\x10\xb1\x14\x0f\xe9\xec\x57\x37\ 638 | \x54\x7f\xad\x36\x50\x8c\xb1\x55\x56\xb1\x9e\x4b\xc8\x18\xf3\xeb\ 639 | \x74\x7d\x5d\xe0\x4f\xb7\xd4\xfc\xd3\x5b\xbd\x07\xfb\x33\x86\x57\ 640 | \xd3\xb5\xd1\x09\xcd\x4e\xff\xc8\xa9\x69\x1e\xa4\xc5\x58\x71\x9f\ 641 | \x13\x09\x53\x0a\x63\xc3\xc3\x16\x56\x94\xe1\x48\x11\x1a\x7c\xf2\ 642 | \xff\x64\xbf\xc2\xd9\xeb\xd1\x16\x27\x33\xcd\xeb\xca\x3d\xff\x7e\ 643 | \x4d\xe5\xf2\xd9\xbe\xe2\x0c\xad\x86\x15\xf1\xbc\x86\x31\xf2\x68\ 644 | \xec\x2b\xe7\xfa\x5f\xbd\xb5\xe6\x5b\x8b\xc2\x9a\x29\xe2\x69\x61\ 645 | \x8d\xb8\xdf\x50\xc2\x3f\x29\x00\x90\xdb\x88\x1b\xef\x84\xc5\x45\ 646 | \x3c\x2d\x34\x53\x7c\x6b\x51\xf8\xd5\x5b\x6b\xbe\x72\xae\xdf\xa3\ 647 | \x15\x37\x79\x8b\xf8\xe4\xe7\x2c\xc6\x68\x4e\xc4\xf8\xe9\xd5\x15\ 648 | \x5f\x39\xdf\xff\x8b\x77\x63\xed\xbd\x99\x14\x23\x8f\x46\x9a\x86\ 649 | \xa1\x0a\x80\x7a\xb2\x33\xc6\x70\x4e\x19\x2e\x7c\x82\x1a\xaa\x3c\ 650 | \xdf\xff\x72\xd9\x0d\xb5\x81\x80\xc7\x89\xab\xba\x45\x0f\xac\xac\ 651 | \x80\x47\xfb\x1f\x17\x85\xbe\xfa\x25\xff\xa6\xbd\x83\x2f\xee\x1b\ 652 | \x3c\x10\x33\x07\x33\x42\x67\x42\xd7\x98\x5e\xe4\x48\x06\x00\x5b\ 653 | \x08\x41\x16\x17\x16\x17\x96\xa0\x90\xce\xea\xca\x3d\x37\x2f\x08\ 654 | \x7d\xfb\x92\xd0\x39\x21\xe7\x7e\x31\x70\x28\xb0\xb2\xce\x09\xe9\ 655 | \xf7\x2f\x29\xfb\xd6\x25\xa1\x97\xda\x13\x6f\xb5\x27\x3a\xfa\xcc\ 656 | \xa3\x29\x9e\xcc\x70\x26\x88\x69\xa4\x69\x4c\x3b\x75\x4a\xef\x64\ 657 | \xb3\x26\x45\xe6\xb6\x81\x92\x58\xf6\x3f\xb2\x5d\x20\x11\x27\x7f\ 658 | \xc1\xe7\x82\x38\x17\x82\x93\x60\xe4\xd5\xd9\xb9\x41\xbd\xb6\xc2\ 659 | \xb8\xa6\x2e\x78\x63\x5d\x70\xa6\x83\x51\x95\xe5\x68\x60\x65\xcd\ 660 | \x0c\xe9\x77\x37\x4c\xfb\xc7\x4b\x42\x6d\xdd\x99\xbf\x74\xa6\xda\ 661 | \x8e\x0f\x75\xc7\xad\xae\x14\xef\x4d\x8b\xa4\xc5\x2d\x8b\x34\x59\ 662 | \x6b\x1a\x88\x88\xa7\xac\xd8\x10\xc7\x94\xcf\x60\x0b\x93\x53\x3c\ 663 | \xc5\xad\x14\x1f\xf4\x4a\xd7\xe5\x05\x11\x27\xd2\x75\x0a\xe8\x5a\ 664 | \xa5\x5f\xab\xf1\x6b\xd5\x61\xbd\xfe\x1c\xdf\xca\xb9\xfe\xfa\x6a\ 665 | \x4f\xc8\x91\x13\xc0\x33\xb9\x10\x58\x59\x21\x8f\xb6\x6c\x96\x6f\ 666 | \xd9\x2c\x5f\xc2\x14\x47\x06\xcc\x4f\xfa\xcc\xf6\xbe\x4c\x47\xbf\ 667 | \x19\x4d\xf1\xb4\x29\xb8\x25\x69\x09\xb0\x48\xf2\xda\x88\x81\xb2\ 668 | \x06\xb0\x85\x47\x63\x17\x55\x19\xff\x50\x1b\xd0\x43\x9a\x54\x43\ 669 | \x2c\xc6\x48\xd3\x99\xd7\x60\x11\xbf\x56\x5b\x6e\xd4\x55\x78\x2e\ 670 | \xac\x30\x66\x4d\x33\x82\x76\xcc\x1a\x5a\x50\xc3\xa4\x0a\x86\xec\ 671 | \x9d\x0a\x69\x8b\x2c\x59\xef\x59\xe0\x44\x3e\x9d\x79\x35\x9c\x1a\ 672 | \x82\x0d\xb2\xb7\x85\xa4\xb9\x90\xad\x0a\x99\x31\xd2\x19\xf3\xea\ 673 | \xc4\x24\xbb\x0a\x22\x57\x60\x01\x00\xe4\x20\x5b\xb2\x03\x00\x8c\ 674 | \x09\x81\x05\x00\xca\x40\x60\x01\x80\x32\x10\x58\x00\xa0\x0c\x04\ 675 | \x16\x00\x28\x03\x81\x05\x00\xca\x40\x60\x01\x80\x32\x10\x58\x00\ 676 | \xa0\x0c\x04\x16\x00\x28\x03\x81\x05\x00\xca\x40\x60\x01\x80\x32\ 677 | \x10\x58\x00\xa0\x0c\x04\x16\x00\x28\x03\x81\x05\x00\xca\x40\x60\ 678 | \x01\x80\x32\x10\x58\x00\xa0\x0c\x04\x16\x00\x28\x03\x81\x05\x00\ 679 | \xca\x40\x60\x01\x80\x32\xfe\x3f\x28\x3d\x2d\xf3\xa0\xbb\xe1\x64\ 680 | \x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ 681 | " 682 | 683 | qt_resource_name = b"\ 684 | \x00\x05\ 685 | \x00\x6f\xa6\x53\ 686 | \x00\x69\ 687 | \x00\x63\x00\x6f\x00\x6e\x00\x73\ 688 | \x00\x08\ 689 | \x0a\x61\x5a\xa7\ 690 | \x00\x69\ 691 | \x00\x63\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\ 692 | " 693 | 694 | qt_resource_struct_v1 = b"\ 695 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ 696 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ 697 | \x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ 698 | " 699 | 700 | qt_resource_struct_v2 = b"\ 701 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ 702 | \x00\x00\x00\x00\x00\x00\x00\x00\ 703 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ 704 | \x00\x00\x00\x00\x00\x00\x00\x00\ 705 | \x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ 706 | \x00\x00\x01\x7f\x24\x90\xc2\x69\ 707 | " 708 | 709 | qt_version = [int(v) for v in QtCore.qVersion().split('.')] 710 | if qt_version < [5, 8, 0]: 711 | rcc_version = 1 712 | qt_resource_struct = qt_resource_struct_v1 713 | else: 714 | rcc_version = 2 715 | qt_resource_struct = qt_resource_struct_v2 716 | 717 | def qInitResources(): 718 | QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) 719 | 720 | def qCleanupResources(): 721 | QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) 722 | 723 | qInitResources() 724 | -------------------------------------------------------------------------------- /resources.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | qrscan.png 5 | 6 | -------------------------------------------------------------------------------- /scripts/config_env.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | color a 3 | echo Creating virtual environment: venv 4 | python -m venv venv 5 | echo Upgrade pip version 6 | .\venv\Scripts\python.exe -m pip install --upgrade pip 7 | .\venv\Scripts\pip.exe install -U setuptools wheel 8 | echo Installing pyqt5 pyqt5-stubs pywin32 pyinstaller opencv-python opencv-contrib-python 9 | .\venv\Scripts\pip.exe install -r requirements.txt -------------------------------------------------------------------------------- /scripts/config_env.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # script will exit when a command occurs error 4 | set -e 5 | 6 | echo Creating virtual environment: venv 7 | python3 -m venv venv 8 | echo Upgrade pip version 9 | venv/bin/python -m pip install --upgrade pip 10 | venv/bin/pip install -U setuptools wheel 11 | echo Installing pyqt5 pyqt5-stubs pywin32 pyinstaller opencv-python opencv-contrib-python 12 | venv/bin/pip install -r requirements.txt -------------------------------------------------------------------------------- /scripts/publish.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | REM Set color in terminal 3 | color a 4 | echo -----------------Publish PyQt project to exe------------------ 5 | echo Set environment variables 6 | REM Set current work dir 7 | set PRJ_PATH=%~dp0 8 | REM Set python code file name 9 | set PY_NAME=pyqt5_qr_scan 10 | REM Set virtual environment name 11 | set PYTHON_NAME=venv 12 | REM set path of pyinstall.exe 13 | set PYINSTALLER_FILE=%PRJ_PATH%\%PYTHON_NAME%\Scripts\pyinstaller.exe 14 | REM set lib of PyQT5 15 | set PYQT_PATH=%PRJ_PATH%\%PYTHON_NAME%\Lib\site-packages\PyQt5\Qt\bin 16 | set SPEC_PATH=%PRJ_PATH%\build 17 | set WORK_PATH=%PRJ_PATH%\build 18 | set DIST_PATH=%PRJ_PATH%\bin 19 | set ICON_FILE=%PRJ_PATH%\qrscan.ico 20 | set FINAL_PATH=QrScan 21 | 22 | rmdir /Q /S %WORK_PATH% 23 | rmdir /Q /S %DIST_PATH% 24 | del resources.py 25 | 26 | REM how to get version.txt template 27 | REM %PRJ_PATH%\%PYTHON_NAME%\Scripts\python.exe %PRJ_PATH%\%PYTHON_NAME%\Lib\site-packages\PyInstaller\utils\cliutils grab_version.py demo.exe 28 | 29 | REM compile images 30 | %PRJ_PATH%\%PYTHON_NAME%\Scripts\pyrcc5.exe resources.qrc -o resources.py 31 | 32 | echo Packing Analysis.py 33 | %PYINSTALLER_FILE% --paths=%PYQT_PATH% --specpath=%SPEC_PATH% --workpath=%WORK_PATH% --distpath=%DIST_PATH% --version-file %PRJ_PATH%\file_version_info.txt --icon=%ICON_FILE% -D -w --clean %PRJ_PATH%\%PY_NAME%.py -y 34 | 35 | echo Creating %FINAL_PATH% 36 | rename "%DIST_PATH%\%PY_NAME%" "%FINAL_PATH%" 37 | md %DIST_PATH%\%FINAL_PATH%\models 38 | 39 | REM xcopy /y "%DIST_PATH%/control" "%FINAL_PATH%\" /e 40 | xcopy /y models\ %DIST_PATH%\%FINAL_PATH%\models /e 41 | 42 | cd %DIST_PATH%\ 43 | tar.exe -a -c -f %FINAL_PATH%.zip %FINAL_PATH% 44 | move %FINAL_PATH%.zip %PRJ_PATH% 45 | cd %PRJ_PATH% 46 | 47 | REM pause -------------------------------------------------------------------------------- /scripts/publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # script will exit when a command occurs error 4 | set -e 5 | 6 | export PRJ_PATH=$(pwd) 7 | export PY_NAME=pyqt5_qr_scan 8 | export PYTHON_NAME=venv 9 | export PYINSTALLER_FILE=${PRJ_PATH}/${PYTHON_NAME}/bin/pyinstaller 10 | export PY_VER=python$(venv/bin/python3 -V | cut -d " " -f 2 | cut -d "." -f 1-2) 11 | export PYQT_PATH=${PRJ_PATH}/${PYTHON_NAME}/lib/${PY_VER}/site-packages/PyQt5/Qt5/lib 12 | export SPEC_PATH=${PRJ_PATH}/build 13 | export WORK_PATH=${PRJ_PATH}/build 14 | export DIST_PATH=${PRJ_PATH}/bin 15 | export ICON_FILE=${PRJ_PATH}/qrscan.ico 16 | export FINAL_PATH=QrScan 17 | 18 | rm -rf ${WORK_PATH} 19 | rm -rf ${DIST_PATH} 20 | 21 | rm -f resources.py 22 | 23 | ${PRJ_PATH}/${PYTHON_NAME}/bin/pyrcc5 resources.qrc -o resources.py 24 | 25 | ${PYINSTALLER_FILE} --paths=${PYQT_PATH} --specpath=${SPEC_PATH} --workpath=${WORK_PATH} --distpath=${DIST_PATH} --version-file ${PRJ_PATH}/file_version_info.txt --icon=${ICON_FILE} -D -w --clean ${PRJ_PATH}/${PY_NAME}.py -y 26 | 27 | mv ${DIST_PATH}/${PY_NAME} ${DIST_PATH}/${FINAL_PATH} 28 | 29 | cp -r models ${DIST_PATH}/${FINAL_PATH}/ 30 | 31 | cd ${DIST_PATH} 32 | zip -q -r ${FINAL_PATH}.zip ${FINAL_PATH} 33 | mv ${FINAL_PATH}.zip ${PRJ_PATH} 34 | cd .. 35 | -------------------------------------------------------------------------------- /sql_helper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # author: 'zfb' 4 | # time: 2023-01-04 19:03 5 | 6 | import sqlite3 7 | 8 | table_files_name = "files.db" 9 | table_status_name = "status.db" 10 | 11 | def create_files_table(): 12 | ''' 13 | files表用于存放未正常结束的操作,已经处理过的图片(只保存最近的一次处理结果) 14 | ''' 15 | conn = sqlite3.connect(table_files_name) 16 | cur = conn.cursor() 17 | try: 18 | sql = """CREATE TABLE if not exists files( 19 | id integer primary key autoincrement, 20 | img_name varchar(1024) not null, 21 | timestamp DATE DEFAULT (datetime('now','localtime')) 22 | );""" 23 | cur.execute(sql) 24 | return True 25 | except Exception as e: 26 | print(e) 27 | return False 28 | finally: 29 | cur.close() 30 | conn.close() 31 | 32 | def create_status_table(db_name="status.db"): 33 | ''' 34 | status表用于上一次处理的状态 35 | ''' 36 | conn = sqlite3.connect(db_name) 37 | cur = conn.cursor() 38 | try: 39 | sql = """CREATE TABLE if not exists status( 40 | id integer primary key autoincrement, 41 | operation varchar(10) not null, 42 | img_path varchar(1024) not null, 43 | cut_path varchar(1024) default null, 44 | finished integer default 0, 45 | timestamp DATE DEFAULT (datetime('now','localtime')) 46 | );""" 47 | cur.execute(sql) 48 | return True 49 | except Exception as e: 50 | print(e) 51 | return False 52 | finally: 53 | cur.close() 54 | conn.close() 55 | 56 | def clean_files_table(): 57 | conn = sqlite3.connect(table_files_name, isolation_level=None) 58 | cur = conn.cursor() 59 | try: 60 | sql = "DELETE FROM files;" 61 | cur.execute(sql) 62 | cur.execute("VACUUM;") 63 | conn.commit() 64 | return True 65 | except Exception as e: 66 | print(e) 67 | return False 68 | finally: 69 | cur.close() 70 | conn.close() 71 | 72 | def insert_file(img_name): 73 | ''' 74 | 存放在files表中的图片,表示已经处理过了 75 | ''' 76 | conn = sqlite3.connect(table_files_name) 77 | cur = conn.cursor() 78 | try: 79 | sql = f"INSERT INTO files (img_name) VALUES ('{img_name}');" 80 | cur.execute(sql) 81 | conn.commit() 82 | return True 83 | except Exception as e: 84 | print(e) 85 | return False 86 | finally: 87 | cur.close() 88 | conn.close() 89 | 90 | def insert_status(operation, img_path, cut_path=None, finished=0): 91 | conn = sqlite3.connect(table_status_name) 92 | cur = conn.cursor() 93 | try: 94 | sql = f"INSERT INTO status (operation, img_path, cut_path, finished) VALUES ('{operation}', '{img_path}', '{cut_path}', {finished});" 95 | cur.execute(sql) 96 | conn.commit() 97 | return True 98 | except Exception as e: 99 | print(e) 100 | return False 101 | finally: 102 | cur.close() 103 | conn.close() 104 | 105 | def exist_file(img_name): 106 | conn = sqlite3.connect(table_files_name) 107 | cur = conn.cursor() 108 | try: 109 | sql = f"SELECT * FROM files WHERE img_name='{img_name}';" 110 | cur.execute(sql) 111 | result = cur.fetchall() 112 | if len(result) == 0: 113 | return False 114 | else: 115 | return True 116 | except Exception as e: 117 | print(e) 118 | return False 119 | finally: 120 | cur.close() 121 | conn.close() 122 | 123 | def get_all_files(): 124 | conn = sqlite3.connect(table_files_name) 125 | cur = conn.cursor() 126 | try: 127 | sql = "SELECT img_name FROM files;" 128 | cur.execute(sql) 129 | result = cur.fetchall() 130 | return result 131 | except Exception as e: 132 | print(e) 133 | return None 134 | finally: 135 | cur.close() 136 | conn.close() 137 | 138 | def get_status(): 139 | conn = sqlite3.connect(table_status_name) 140 | cur = conn.cursor() 141 | try: 142 | # 按id降序排列,取第一条 143 | sql = "SELECT operation, img_path, cut_path FROM status WHERE finished=0 ORDER BY id DESC LIMIT 1;" 144 | cur.execute(sql) 145 | result = cur.fetchall() 146 | if len(result) == 0: 147 | return None 148 | return result[0] 149 | except Exception as e: 150 | print(e) 151 | return None 152 | finally: 153 | cur.close() 154 | conn.close() 155 | 156 | def clean_status_table(): 157 | conn = sqlite3.connect(table_status_name, isolation_level=None) 158 | cur = conn.cursor() 159 | try: 160 | sql = "DELETE FROM status;" 161 | cur.execute(sql) 162 | cur.execute("VACUUM;") 163 | conn.commit() 164 | return True 165 | except Exception as e: 166 | print(e) 167 | return False 168 | finally: 169 | cur.close() 170 | conn.close() -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # author: 'zfb' 4 | # time: 2023-12-25 18:26 5 | 6 | import sys 7 | # from os import getcwd 8 | from os.path import dirname, abspath 9 | 10 | def get_base_path(): 11 | """ 12 | 获取当前运行目录,适应于Python和PyInstaller环境 13 | """ 14 | # path = getcwd() 15 | path = dirname(abspath(__file__)) 16 | if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'): 17 | # 如果是PyInstaller环境 18 | # 可以使用 sys.executable 获取当前运行的exe路径 19 | # 也可以使用 sys._MEIPASS 获取当前运行的exe所在目录下的_internal文件夹的路径 20 | # 例如 D:\QrScan\bin\QrScan\_internal 21 | # 获取 _internal 文件夹的路径,然后使用 dirname 获取上一级目录 22 | path = dirname(sys._MEIPASS) 23 | return path --------------------------------------------------------------------------------