How to save images to a server folder via sockets using python and opencv?

1
Hello, I'm new to programming and would like to know how to save images, (captured by opencv) in a folder created by the code inside the server, I know how to do this with the sockets but I have no idea how. the code below captures the face creates a folder and saves 100 images of it, I need this folder to be inside a server.

import cv2, sys, numpy, os
haar_file = 'haarcascade_frontalface_default.xml'
datasets = 'datasets'  #All the faces data will be present this folder
sub_data = raw_input ('digite o seu nome')     #These are sub data sets of folder, for my faces I've used my name

path = os.path.join(datasets, sub_data)
if not os.path.isdir(path):
    os.mkdir(path)
(width, height) = (130, 100)    # defining the size of images 


face_cascade = cv2.CascadeClassifier(haar_file)
webcam = cv2.VideoCapture(0) #'0' is use for my webcam, if you've any other camera attached use '1' like this

# The program loops until it has 100 images of the face.
count = 1
while count < 101: 
    (_, im) = webcam.read()
    gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
    faces = face_cascade.detectMultiScale(gray, 1.3, 4)
    for (x,y,w,h) in faces:
        cv2.rectangle(im,(x,y),(x+w,y+h),(255,0,0),2)
        face = gray[y:y + h, x:x + w]
        face_resize = cv2.resize(face, (width, height))
        cv2.imwrite('%s/%s.png' % (path,count), face_resize)
    count += 1

    cv2.imshow('OpenCV', im)
    key = cv2.waitKey(10)
    if key == 27:
        break
    
asked by anonymous 07.04.2017 / 18:05

1 answer

2

You know that sockets are a low level of network programming, are not they? It's a point where you have to worry about each byte read, send messages - etc ... are so complex details, that in the real world, there are protocols built on the sockets to abstract details.

So I could give you an example of how to save a file listening on the raw socket here - but it would be something complicated - we would have to devise an 'ad hoc' protocol - if only to know when the file name be saved had arrived - and at least one field to know the size of the file.

Well, HTTP is the protocol used by the Web, which puts a good number of abstractions into the messages - it specifies headers, and "Post" methods - so using the Flask framework, for example, would be possible make a minimalist application just to save files with maybe 5 or 6 lines in total. But this implementation would still require you to retrieve the data and content of the body of the HTTP message, which is like what is posted on a form on a web page - has some more bureaucracy.

Python, however, has long-standing versions of a remote method call server that responds to HTTP, and encodes the parameters of the methods as XML transparently. This is in the python library under "xmlrpc". The Python implementation is from a more "innocent" time - it does not consider anything security - and in Python 2, no data conversion as well. By switching to Python3, using Python's xmlrpc got a bit more bureaucratic - some considerations of server consistency and conversion of text-etnram data into game - but it's still going to be orders of magnitude simpler than doing an equivalent implementation in Sockets . (Just about 5 times simpler than deploying on sockets without any security considerations, etc ...).

Note that an XMLRPC server will respond to any request without any type of authentication - not even a static token - so if you are not on a closed network between your client and server, it is best to use Flask or Pyramid to put some authentication - and set up an HTTP server up front, such as NGINX to provide encryption by https for your data. (But if the two machines are on the internet, read about creating "ssh tunnels" - it's going to be a lot simpler and safer than putting a web-server with authentication just for that. server to allow connection to the xmlrpc port only through the tunnel.)

With this in mind, Python XMLRPC server example to save a file in the "date /" folder ( adapted from official documentation ):

from xmlrpc.server import SimpleXMLRPCServer
from xmlrpc.server import SimpleXMLRPCRequestHandler
from xmlrpc.client import Binary

# Restrict to a particular path.
class RequestHandler(SimpleXMLRPCRequestHandler):
    rpc_paths = ('/RPC2',)

# Create server
with SimpleXMLRPCServer(("0.0.0.0", 8010), allow_none=True,
                        requestHandler=RequestHandler) as server:
    #server.register_introspection_functions()

    def save_image(name, content):
        # Dados do tipo "bytes" chegam aqui wrapped na classe "Binary"
        if isinstance(content, Binary):
            content = content.data
        with open("data/" + name.replace("..", ""), "wb") as file_:
            file_.write(content)

    server.register_function(save_image, "save_image")

    server.serve_forever()

And to use "save_image" on your client, as if it were a call to a local method, these three lines are enough:

import xmlrpc.client
s = xmlrpc.client.ServerProxy('http://localhost:8010')
s.save_image(<nome_do_arquivo como string>, <conteudo do arquivo como bytes>)

Note that although very insecure, I still put a "replace" in the name to avoid a very simple type of attack in which the name of the image is put paths of type "../../etc/shadow" o which would overwrite the system password configuration file (if xmlrpc is running as root, of course).

    
08.04.2017 / 17:05