Opencv reading video files, video stream, Images, IP, and Web cameras. I would like to cover this all in one post. Yes, video writing is also important to store your results and achievements in video. There is a couple of simple tricks and if you follow them, you will never have a problem with reading and writing video, streaming, files in the future.

opencv web camera

Basic OpenCV web camera reading

OpenCV Prerequisites: Getting Your Setup Right

Have you ever spent hours just trying to get your C++ environment to compile, only to be met with endless linking errors? I know that struggle all too well! Setting up OpenCV doesn't have to be a headache if you follow a few simple shortcuts.

On the Windows platform, my absolute favorite way to get started is through the NuGet package system. It’s a total lifesaver because it sets up your project without you needing to touch linking settings, library paths, or global environment variables manually.

Streamlining Your Installation


With NuGet, you can literally start coding in seconds. Just select the package, install it, and you’re ready to compile. It's the fastest way to get your "feet wet" with computer vision without the configuration nightmare.

However, if you're looking for a more modern, automated approach to handle complex builds—especially if you need FFmpeg support highly recommend checking out my latest post on building OpenCV with FFmpeg using an AI agent. It's a game-changer for custom installations!

Mastering OpenCV: How to Read and Write Video, Images, and IP Streams

Have you ever spent hours just trying to get a video feed to appear, only to be met with a blank window or a "file not found" error? I've been there, and I know exactly how frustrating it can be! Whether you're a hobbyist or a professional, mastering VideoCapture and VideoWriter is the foundation of every great computer vision project.

In this guide, I’m going to share my personal "fail-proof" tricks for handling everything from local files to live IP camera streams. Let’s dive in!


The Essential Headers You Need

Before we write a single line of logic, you need the right tools. I always make sure these headers are included to avoid those annoying "undefined" errors:

highgui.hpp: For creating the user interface and displaying your results.

core.hpp: The backbone of OpenCV containing basic structures like Mat.

imgproc.hpp: Essential for any image processing or filtering tasks.

videoio.hpp: The most critical header for reading and writing video files or streams.

imgcodecs.hpp: Used specifically for reading and writing static image files.

Pro Tip: If you are planning on streaming from an IP camera, you will almost certainly need all of these to ensure your stream handles various network protocols correctly.

1. Reading from a Web Camera

Opening your default webcam is the easiest way to start. When you use VideoCapture cap(0);, you are telling OpenCV to grab the first available camera (usually your laptop's built-in webcam). I use a for(;;) loop to keep the feed running until the camera is closed or the user exits.

#include "opencv2\imgproc.hpp"
#include "opencv2\objdetect\objdetect.hpp"
#include "opencv2\videoio\videoio.hpp"
#include "opencv2\imgcodecs\imgcodecs.hpp"

#include "opencv2\core\core.hpp"
#include "opencv2\highgui.hpp"

#include <vector>
#include <stdio.h>
#include <windows.h>
#include <iostream>
#include <time.h>

using namespace cv;
using namespace std;

int main(int argc, const char** argv)
{
 VideoCapture cap(0);
 for (;;)
 {
if (!cap.isOpened()) {
   cout << "Video Capture Fail" << endl;
   break;
  }
else {
   Mat img;
   cap >> img;
   namedWindow("Video", WINDOW_AUTOSIZE);
   imshow("Video", img);

   int key2 = waitKey(20);
  }
 }
 return 0;
} 


2. Reading Video Files

Reading a saved file is almost identical to reading a camera feed. Instead of the device ID (0), I just pass the file path. One thing I've learned: always double-check your file path. If your video isn't loading, try using the full absolute path.

VideoCapture cap("movie.vmw");
VideoCapture cap("movie.mp4");
VideoCapture cap("movie.mov");
VideoCapture cap("movie.xxx");
VideoCapture cap("C:/cm/movie.mov");
VideoCapture cap("C:/cm/movie.mp4");

3. Images: Reading and Writing

Loading a single image is a breeze with imread. I often use flags like IMREAD_COLOR (or the older CV_LOAD_IMAGE_COLOR) to ensure I’m getting the 3-channel BGR data I expect. If you just need a single channel, GRAYSCALE is your best friend for performance.

Mat image;
image = imread("C:/adress/6.jpg", CV_LOAD_IMAGE_COLOR);

To save your results after processing, simply use imwrite. It’s that simple!

imwrite("image.jpg", image);

4. The Secret to IP Camera Streams

Streaming from an IP camera can be tricky because every manufacturer uses a different URL format. My personal "Golden Rule" is to verify the stream in VLC Player first. If it works in VLC, it will work in OpenCV!

Remember, while VLC might pop up a box asking for your password, OpenCV won't. You need to embed the credentials directly into the URL: rtsp://username:password@IP:PORT.

// Common URL Formats
http://IP:PORT/mjpeg/video.mjpg?counter
rtsp://IP:PORT/various url
rtsp://IP:PORT/axis-cgi/mjpg/video.cgi
http://IP:PORT/mjpg/video.mjpg
("rtsp://USER:PASS@xxx.xxx.xxx.xxx/axis-media/media.amp?camera=2")

Advanced: Multi-Threaded IP Streaming

If you are trying to read from multiple cameras, doing it in a single loop will cause massive lag. I prefer using std::thread to handle each stream independently. This allows one camera to process while the other is still grabbing a frame.

#include <iostream>
#include <thread>
#include "opencv2/opencv.hpp"
#include <vector>

using namespace std;
using namespace cv;

void detect(Mat img, String strCamera) {
  string cascadeName1 = "haar_cascade_for_people_detection.xml";
  CascadeClassifier detectorBody;
  bool loaded1 = detectorBody.load(cascadeName1);
  Mat original;
  img.copyTo(original);
  vector<Rect> human;
  cvtColor(img, img, CV_BGR2GRAY);
  equalizeHist(img, img);
  detectorBody.detectMultiScale(img, human, 1.1, 2, 0 | 1, Size(40, 80), Size(400,480 ));
  if (human.size() > 0) 
    {
      for (int gg = 0; gg < human.size(); gg++) 
      {
      rectangle(original, human[gg].tl(), human[gg].br(), Scalar(0, 0, 255), 2, 8, 0);
      }
    }
  imshow("Detect " + strCamera, original);
  int key6 = waitKey(40);
}

void stream(String strCamera) {
  VideoCapture cap(strCamera);
  if (cap.isOpened()) { 
      while (true) {
        Mat frame;
        cap >> frame; 
        resize(frame, frame, Size(640, 480));
        detect(frame, strCamera);
      }
   }
}

int main() {
    thread cam1(stream, "http://xxxxxxxR");
    thread cam2(stream, "http://xxxxxxxR");
    cam1.join();
    cam2.join();
    return 0;
}

5. Writing Video: The "Golden Rule"

This is where most people get stuck. If you want to save your video to a file, your Mat frame size MUST match the VideoWriter size exactly. If they are even one pixel off, the file will be 0kb or unplayable. I always resize my frame right before writing to be safe.

Size SizeOfVideo = cv::Size(1024, 740);  
VideoWriter video("Result.wmv", CV_FOURCC('W', 'M', 'V', '2'), 25, SizeOfVideo, true);

// ALWAYS resize to match your VideoWriter dimensions!
resize(image, image, Size(1024, 740)); 

video << image; 
// OR 
video.write(image);

Key Takeaways for Success

Check your paths: Relative paths are the #1 cause of "empty" Mat errors.

VLC is your friend: Always test IP streams in VLC before coding.

Match your sizes: VideoWriter will fail silently if your frame size doesn't match the writer's setup.

Use Threads: Don't try to process multiple IP streams in a single thread if you want real-time performance.

Have you had any "fun" experiences with IP camera URLs? They can be a real headache! Let me know in the comments which brand of camera you're working with, and I might be able to help with the URL format!