jeffbass / imagezmq

A set of Python classes that transport OpenCV images from one computer to another using PyZMQ messaging.
MIT License
1.01k stars 159 forks source link

How to scale ImageHub to work for 200+ cameras #54

Open Udayaprasad opened 3 years ago

Udayaprasad commented 3 years ago

Hi @jeffbass,

We are working on one of the video surveillance project, where we need to process 200+ camera feeds to multiple computer vision algorithms. This project looks great, but can you suggest the best way to scale the ZMQ setup?

Thank, Uday

jeffbass commented 3 years ago

Hi Uday @Udayaprasad,

My project architecture has many cameras sending images to a few hub computers that analyze those images. The imageZMQ package is just an image transport tool. It suits my own project perfectly, but there are several questions that might help you decide if imageZMQ will scale well for you.

  1. Do you need the cameras to send every image? Or can you pair the camera with a local edge computer (e.g. Raspberry Pi) to selectively send only some subset of relevant images?
  2. Are you OK with image compression (e.g. jpg) before sending?
  3. Do you need a series of still images in a stream or do you need an actual video stream (they are not the same thing)?
  4. Do all your cameras need to send images at the same time?
  5. Do you want to use the REQ/REP or the PUB/SUB messaging pattern of ZMQ?
  6. How big do your images need to be?

Here are my thoughts:

  1. Sending a subset of images works well in my project. I have 24 Raspberry Pi computers with attached cameras capturing images at 16-32 FPS. That means 1 to 3 million frames a day per camera. But, I run a program in each Raspberry Pi that sends only a small fraction of those images. The image selection code only sends images that meet certain criteria (person detected, vehicle detected, coyote detected etc.). This means the network never gets bogged down and the hubs have no trouble keeping up. But that would not be possible if I was sending all of the images from every camera.
  2. OpenCV images are large; compressing them to jpgs lowers the network load by 70 to 90%. But the jpgs lose some image quality (not much and it doesn’t affect my own use case). And the compression itself takes significant time on a Raspberry Pi. It is a tradeoff of higher network load for raw OpenCV images versus higher CPU load for jpg compressed images. I have found that sending jpgs works best for me, but it is worth running timing tests because image size, image heterogeneity, etc. can make a big difference.
  3. Images versus video: My own application is about analyzing individual frames at the hub computers. So sending individual frames (which is what imageZMQ does) works well for me. But you should consider whether video would work for you. A video stream does not send every image; it sends a full image (a “reference” image), then sends only the parts of the image that change for a period of time until it sends the next reference image. There are many video codecs and video compression tools, but all of them use some sort of frame to frame encoding that specifically AVOIDS sending every frame. Netflix could never stream movies if it actually sent all the frames. Sending video is almost always faster than sending individual image frames. Image compression to jpg images is not the same as video compression because when compressing images to jpgs, every image is compressed individually with no information or “deltas” from previous or subsequent images. The imageZMQ package sends individual images (with optional jpg compression), but it does not send compressed video. Compressed video may be better choice for 200 cameras.
  4. Do all your cameras need to send images at the same time? In my own setup, I have the network topology set up so that cameras that are less likely to send images at the same time share a network. This means my driveway cam watching the mailbox (which has relevant images sent during the daytime) can share a network hub with a infrared coyote cam behind the barn really well, since these 2 cameras will never send images at the same time. But I design my network so that the multiple infrared coyote cams are on different sub networks, since they are more likely to send at the same time. This kind of time sharing analysis allowed me to optimize my different subnets and optimize bandwidth. I found it helpful, but that may not be possible for you.
  5. REQ/REP versus PUB/SUB messaging pattern: There are 2 different messaging patterns available in imageZMQ: REQ/REP and PUB/SUB. There are many advantages and disadvantages to each of them. Depending on how your cameras are networked and how powerful your hub computers are, PUB/ SUB may be faster, but PUB/SUB can also drop some frames when the network is busy. I use REQ/REP in my project. You can read more about imageZMQ messaging patterns in these docs.
  6. How big do your images need to be? While large images look good on the screen or in a photo album, they are often overkill for simple computer vision tasks. Many computer vision machine learning techniques need to reduce the image size to something small (256 x 256 pixels is a common size) to do image classification or object detection. The smaller your image size, the faster you computer vision pipeline will be and the less you will overload your network. I have found that 640 x 480 pixel images are large enough for my projects; they take a LOT less bandwidth that 1080p or larger images. And for some of my images, 320 x 240 pixels is enough to get a particular task done (like reading a water meter).

I have an overview of my Yin Yang Ranch project that uses imageZMQ in this GitHub repo: I also gave a 30 minute PyCon 2020 presentation about it. (Here is the slide deck for that if you want the outline without the talk itself).

Here are some other lessons I have learned as I scaled to larger numbers of cameras using imageZMQ. This comes from a post I made on a message board about ways to set up a network of cameras using imageZMQ. Some of it may be helpful to you; some of it is a restatement of the above ideas:

Feel free to ask follow on questions in this thread and I’ll do my best to answer them. Also, please share your learnings as you build out your own system. If you find something better than imageZMQ for scaling to 200 cameras, please comment in this thread and let me (and the other imageZMQ users) know. All of us are always iterating to newer and faster tools.

Jeff

Udayaprasad commented 3 years ago

Thank you for the detailed explanation, @jeffbass.

1) We would like to keep 15 fps for each camera (compressed to 416X416), also we are using RTSP protocol to get the camera feeds. Each camera is running its own thread. 2) PUB/SUB model will be better for us because we need to transfer each model's predictions to other models for better reusability (Attached example diagram).

I will sure keep this open and provide my findings as and when I am successful with the whole integration

image