CAPTCHA, special case: we break a neural network with thirty lines of code

   I don’t remember how I came across the article habr.com/ru/post/464337 , but it sunk into my brain and did not give rest until the last day. Several times I tried to understand what was happening, a couple of times I tried to make it work, but to no avail: I do not understand anything at all in neural networks and even program like a real programmer.
happy captcha


   Finally, a few days ago, I overpowered the launch of the python and decided, why not and so on. Having forgotten everything that I read in the mentioned article, I went my own way.
   Remembering the myriad of resolved captchas, I suggested that you can solve them by banal comparison with the mask, which was later confirmed.
   First, manually assembled test captcha (83 pieces) and gave them obvious names. The script turned them into bitmaps.

   The numbers in the captcha are two sizes in height with a difference of 1 pixel and three to four faces in width. The baseline of all characters in all captcha is the same. All this diversity, as it turned out, has a certain common mask, a comparison with which uniquely identifies a figure. I cut out several (at first - 5, then added another 1-2; with "4" it took longer than the rest) of the same numbers from different captchas. In paint.net, I put them on top of each other and got a mask that is common to all faces of each digit.

   I discovered the only problem later, already during mass processing, but successfully bypassed it
with a crutch
   , — «1», «2» .. «9». , , «4», «4», «1». , -, «123456789» «423156789» -, «4» , «1».

   In addition to this small misunderstanding, the noise does not interfere at all. The result of this stage was a set of 9 masks. Two nested loops and voila! - all my 83 captchas are recognized with a bang!

   

   Then the question arose: where to get a large set of captcha for verification. And I downloaded “29,000 captcha” from the mentioned article.
However, this turned out to be a waste of time.
   - (, -, .. ), : : 6503 , 5420 , 760 .. – .. 14882, , , .
-, – -, – . PNG, – JPG, , . , – «”” ».

   So I had to uncover Google and mine the perfect captcha on my own: 3224 files were accumulated per night, including 49 completely empty ones, as it turned out later. Thank you Ganesha for the code .

   Actually recognition of captcha fits into 26 lines of boring python code. From external modules only PIL is needed. The speed is about 1000 captcha per minute (one thousand captcha per minute) on the old Core 2 “four cores four gigs”. On a more decent eight-stream i5 is noticeably faster, although the matter, of course, is not in the threads. Recognition of 100% or very close to that: spot check showed no errors.

   Of course, all this is not interesting in the sense of neural networks and other blockchains, but it has a very definite advantage over the previously proposed option: speed and accuracy. It is also true that any change in the parameters of the captcha - headset or font size, type of noise, etc. - will lead to the complete inoperability of my decision.

Download the archive with captcha from Yandex.Disk (14MB).

Source
from PIL import Image, ImageTk

def recognize(filepath):
  Zlist = [] # [(x1, z1), (x2, z2), (x3, z3), etc.] - position and digit
  captcha = ""
  originalimage = Image.open(filepath).convert('L').point(lambda x : 255 if x > 20 else 0, mode='1').convert('1').convert('RGBA')
  if originalimage.getextrema() == ((0, 0), (0, 0), (0, 0), (255, 255)):
    return("empty image")
  for z in [4, 2, 3, 1, 5, 6, 7, 8, 9]: # reorder to exclude false 1 on 4
    mask = Image.open('mask' + str(z) + '.png').convert('RGBA')
    previ = 0
    for i in range(15, 120): # no digit in left part
      resultimage = Image.alpha_composite(originalimage.crop((i, 0, i + 30, 0 + 50)), mask)
      if resultimage.getextrema() == ((0, 0), (0, 0), (0, 0), (255, 255)):
        if z == 4: # delete 4 to exclude false 1 on 4
          maskx = Image.open('mask4x.png').convert('RGBA') 
          originalimage.paste(Image.alpha_composite(originalimage.crop((i, 0, i + 30, 0 + 50)), maskx), (i, 0))
        if previ == 0 or i > previ + 15: #no digit closer then 15 px
          Zlist.append((i, z))
          if len(Zlist) == 5:
              Zlist.sort()
              for z in Zlist:
                captcha = captcha + str(z[1])
              return(captcha)
          previ = i
          i = i + 15 #skip a little
  Zlist.sort()
  return(str(Zlist)) #if less then 5 digits recognized
	
def main():
  captcha = recognize(entry.path)
#----------------------------------------------#
#          #
#----------------------------------------------#

main()




Update as of February 13, 2020.
   What was it all about? Not for the sake of sports recognition of saved images? No, all this was purely for pragmatic purposes.
   Ready solution for work. - Local http recognition server plus extension for Chrome.
   So far, the only thing that it can (I hope that can) is to automatically insert the captcha in the right place. The plans:
  - clean the site interface, leaving the necessary minimum;
  - automate captcha updating when viewing information, as one captcha makes it possible to open only 4 objects.
  - Download all prepared statements at once, and not one at a time.

Update as of March 5, 2020.
   Ready solution for work.- Local http recognition server plus extension for Chrome.
   Updated the extension for Chrome. Now it can, in addition to captcha auto-substitution,
 1. when opening pages with information about real estate objects, expand information about rights;
 2. Collect information from these pages for further processing.
   Screenshot in the comment habr.com/post/488018/#comment_21360646

Update as of April 17, 2020 .
   Bot for ordering statements from the list - due to the restriction on the frequency of ordering statements - 1 statement in 5 minutes. Screenshot in comment

All Articles