1

I have written a python code. It gets the video from the camera at 30 fps. Now I have found a very good C++ open source code library that takes the image and perform my desired function. As it is open source code. SO i have its code.

The Problem is it is in C++ and i am writing my code in Python. I need to send an image to that C++ code , process it there and send back the processed image to Python.

I have read numerous questions on stackoverflow and youtube. All answers require some background knowledge of how to send data from C++ to python and vice versa.

As i dont know how to send a data between C++ and python. Could anyone can explain how to send images between them from step 1.

user3585510
  • 131
  • 2
  • 10
  • A simple HACK(meant for dev use only) would be: Write the images you recieve from the webcam and read the same image in C++, you can do this by calling the cpp executable with image_file_path as param. Once you are sure it is working as required then you may invest your time in integrating the native code to your python script – ZdaR Feb 08 '17 at 07:23
  • Actually i am getting a real time video. Video may be atleast 5-6 min duration. As i am getting 30 frames per second . So ithink it wouldn't be appropiate to save 30 images per second and do it for like 5-6 min atleast – user3585510 Feb 08 '17 at 07:26
  • I suggested the HACK for validating your assumptions about the C++ script, if you are sure that the cpp code is working as expected then, here is thread with all possibilities: http://stackoverflow.com/questions/1153577/integrate-python-and-c – ZdaR Feb 08 '17 at 07:28
  • Possible duplicate of [Integrate Python And C++](http://stackoverflow.com/questions/1153577/integrate-python-and-c) – ZdaR Feb 08 '17 at 07:28
  • Maybe you don't need to *send* the image at all http://stackoverflow.com/a/145436/2836621 – Mark Setchell Feb 08 '17 at 07:42
  • As you all have worked in this domain. What would be the most suitable for sending image between them? What do you think is the best among all – user3585510 Feb 08 '17 at 07:52

1 Answers1

1

Its weird nobody sought to solve this problem even 4.9 years later. Here's how I did it using ZMQ. I used PUSH/PULL architecture to send image (.ppm) file from a Python3 client (PUSH) to C++ server (PULL).

The process requires manually obtaining the length/size of the image-encoded-into-base64-string, printed in my python program. This size is then used to determine the buffer size required by the C++ server before it can receive the data.

client.py

import time
import zmq
import base64

def producer():
    # setup socket
    context = zmq.Context()
    zmq_socket = context.socket(zmq.PUSH)
    zmq_socket.bind("tcp://127.0.0.1:5557")

    # Read file content
    f = open("/home/virus/Desktop/optimisation/test.ppm",'rb')
    bytes = bytearray(f.read())

    # Encode to send
    strng = base64.b64encode(bytes)
    print("Sending file over")
    print("\n\nEncoded message size: ",len(strng)) # 4194328 in my case
    zmq_socket.send(strng)
    f.close()

producer()

server.cpp

#include <zmq.h>
#include <vector>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fstream> // for writing files
#include <iostream>

typedef unsigned char uchar;

using namespace std;

static string base64_decode(const string &in) {
    // Ref: https://stackoverflow.com/a/34571089/9625777
    string out;
    vector<int> T(256,-1);
    for (int i=0; i<64; i++)
        T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i;

    int val=0, valb=-8;
    for (uchar c : in) {
        if (T[c] == -1) break;
        val = (val << 6) + T[c];
        valb += 6;
        if (valb >= 0) {
            out.push_back(char((val>>valb)&0xFF));
            valb -= 8;
        }
    }
    return out;
}

int main ()
{
    while(1)
    {
      // Create socket
      void *context = zmq_ctx_new ()
      void *requester = zmq_socket (context, ZMQ_PULL)
      if(zmq_connect (requester, "tcp://localhost:5557")!=0)
      {
        // The zmq_connect() function returns zero if successful.
        // Otherwise it returns -1
        cout << "No connection found\n";
        continue;
      }
      cout << "Got a connectopn\n";

      // Receive data
      char buffer [4194328];
      zmq_recv (requester, buffer, 4194328, 0)
      //cout << buffer;

      // decode data
      auto decodedData = base64_decode(buffer);

      // write results to a file
      ofstream myFile("res.ppm");
      myFile << decodedData;
      myFile.close();

      // Close socket
      zmq_close (requester);
      zmq_ctx_destroy (context);
    }
    return 0;
}


As an option, PUSH/PULL can also be substituted with REQ/REP

client.py

import time
import zmq
import base64

def producer():
    context = zmq.Context()
    zmq_socket = context.socket(zmq.REQ)
    zmq_socket.connect("tcp://127.0.0.1:5556")
    # Start your result manager and workers before you start your producers

    f = open("/home/virus/Desktop/optimisation/test.ppm",'rb')
    #data = f.read
    bytes = bytearray(f.read());#print('\n \t bytes: ',bytes)
    print("bytes len",len(bytes))
    strng = base64.b64encode(bytes)
    #serializedImage = { 'data' : strng }
    #print("sending string: ",strng);
    print("\n\n size: ",len(strng));
    #request = zmq_socket.recv();
    zmq_socket.send(strng)
    print("sent\n")
    result = zmq_socket.recv();
    m = memoryview(result)
    print("\n\nreceived: ",len(result))
    f.close()
    zmq_socket.close()

producer()

server.cpp

#include <zmq.h>
#include <assert.h>
#include <vector>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fstream> // for writing files
#include <iostream>

typedef unsigned char uchar;

using namespace std;
vector<pair<int,int>> arr;

static std::string base64_encode(const std::string &in) {

    std::string out;

    int val = 0, valb = -6;
    for (uchar c : in) {
        val = (val << 8) + c;
        valb += 8;
        while (valb >= 0) {
            out.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(val>>valb)&0x3F]);
            valb -= 6;
        }
    }
    if (valb>-6) out.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[((val<<8)>>(valb+8))&0x3F]);
    while (out.size()%4) out.push_back('=');
    return out;
}

static string base64_decode(const string &in) {
    // Ref: https://stackoverflow.com/a/34571089/9625777
    string out;
    vector<int> T(256,-1);
    for (int i=0; i<64; i++)
        T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i;

    int val=0, valb=-8;
    for (uchar c : in) {
        if (T[c] == -1) break;
        val = (val << 6) + T[c];
        valb += 6;
        if (valb >= 0) {
            out.push_back(char((val>>valb)&0xFF));
            valb -= 8;
        }
    }
    return out;
}

int main ()
{
    while(1)
    {
      // Create socket
      void *context = zmq_ctx_new ();
      void *responder = zmq_socket (context, ZMQ_REP);
      int rc = zmq_bind(responder, "tcp://*:5556");
      assert (rc == 0);
      //{
        // The zmq_connect() function returns zero if successful.
        // Otherwise it returns -1
      //}
      cout << "Got a connectopn\n";

      // Send Request
      //int rc = zmq_send(responder, "ABC", 3,ZMQ_DONTWAIT);
      //assert(rc != -1);

      // Receive data/Request
      char buffer [4194328];
      auto nbytes = zmq_recv (responder, buffer, 4194328, 0);assert (nbytes != -1);
      cout << "Got a request";
      // Generate data/results/ dummy data rn
      /*for(int i=0;i<10;i++){
        for(int j=0;j<10;j++){
            arr.push_back(i);
        }
      }*/

      int a[2];a[0]=3;a[1]=5;
      // Send Result/Response
      rc = zmq_send(responder, a, sizeof(a),0);
      assert(rc != -1);

      // decode data
      auto decodedData = base64_decode(buffer);

      // write results to a file
      ofstream myFile("res.ppm");
      myFile << decodedData;
      myFile.close();

      // Close socket
      zmq_close (responder);
      zmq_ctx_destroy (context);
    }
    return 0;
}

Run as

gcc -Wall -g server.cpp -lzmq -lstdc++ -o s

Hope it helps .

Pe Dro
  • 2,651
  • 3
  • 24
  • 44