如何在 OpenCV 中捕获图像并以 pgm 格式保存?

发布于 2024-09-06 19:24:22 字数 392 浏览 6 评论 0原文

我对一般编程是全新的,正在开发一个项目,我需要从网络摄像头捕获图像(可能使用 OpenCV),并将图像保存为 pgm 文件。

最简单的方法是什么? Willow Garage 提供了以下用于图像捕获的代码:

http://opencv.willowgarage.com/wiki/CameraCapture

使用此代码作为基础,我如何将其修改为:

  1. 每 2 秒从实时摄像头捕获图像
  2. ,将图像以 pgm 格式保存到文件夹中

非常感谢您提供的任何帮助!

I am brand new to programming in general, and am working on a project for which I need to capture images from my webcam (possibly using OpenCV), and save the images as pgm files.

What's the simplest way to do this? Willow Garage provides this code for image capturing:

http://opencv.willowgarage.com/wiki/CameraCapture

Using this code as a base, how might I modify it to:

  1. capture an image from the live cam every 2 seconds
  2. save the images to a folder in pgm format

Thanks so much for any help you can provide!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

ま昔日黯然 2024-09-13 19:24:22

首先,请使用较新的网站 - opencv.org。使用过时的引用会导致连锁效应,当新用户看到旧的引用时,会阅读旧的文档并再次发布旧的链接。

实际上没有理由使用旧的 C API。相反,您可以使用较新的 C++ 接口,它可以优雅地处理视频捕获。以下是 VideoCapture 上文档的示例的简短版本:

#include "opencv2/opencv.hpp"

using namespace cv;

int main(int, char**)
{
    VideoCapture cap(0); // open the default camera
    if(!cap.isOpened())  // check if we succeeded
        return -1;

    for(;;)
    {
        Mat frame;
        cap >> frame; // get a new frame from camera
        // do any processing
        imwrite("path/to/image.png", frame);
        if(waitKey(30) >= 0) break;   // you can increase delay to 2 seconds here
    }
    // the camera will be deinitialized automatically in VideoCapture destructor
    return 0;
}

另外,如果您是编程新手,请考虑使用 OpenCV 的 Python 接口 - cv2 模块。 Python 通常被认为比 C++ 更简单,使用它您可以直接在交互式控制台中使用 OpenCV 函数。使用 cv2 捕获视频看起来像这样(采用的代码来自 此处):

import numpy as np
import cv2

cap = cv2.VideoCapture(0)

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()
    # do what you want with frame
    #  and then save to file
    cv2.imwrite('path/to/image.png', frame)
    if cv2.waitKey(30) & 0xFF == ord('q'): # you can increase delay to 2 seconds here
        break

# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()

First of all, please use newer site - opencv.org. Using outdated references leads to chain effect, when new users see old references, read old docs and post old links again.

There's actually no reason to use old C API. Instead, you can use newer C++ interface, which, among other things, handles capturing video gracefully. Here's shortened version of example from docs on VideoCapture:

#include "opencv2/opencv.hpp"

using namespace cv;

int main(int, char**)
{
    VideoCapture cap(0); // open the default camera
    if(!cap.isOpened())  // check if we succeeded
        return -1;

    for(;;)
    {
        Mat frame;
        cap >> frame; // get a new frame from camera
        // do any processing
        imwrite("path/to/image.png", frame);
        if(waitKey(30) >= 0) break;   // you can increase delay to 2 seconds here
    }
    // the camera will be deinitialized automatically in VideoCapture destructor
    return 0;
}

Also, if you are new to programming, consider using Python interface to OpenCV - cv2 module. Python is often considered simpler than C++, and using it you can play around with OpenCV functions right in an interactive console. Capturing video with cv2 looks something like this (adopted code from here):

import numpy as np
import cv2

cap = cv2.VideoCapture(0)

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()
    # do what you want with frame
    #  and then save to file
    cv2.imwrite('path/to/image.png', frame)
    if cv2.waitKey(30) & 0xFF == ord('q'): # you can increase delay to 2 seconds here
        break

# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
眼趣 2024-09-13 19:24:22

由于 ffriend 的答案仅部分正确,我将添加更多内容(用 C++ 编写)。这个问题的作者明确要求导出为 PGM(以 8 位存储每个像素的 PXM 文件格式)而不是 PNG(正如 ffriend 在他/她的回复中描述的那样)。这里的主要问题是 imwrite 的官方文档 是omho 完全不清楚这个问题:

对于 PPM、PGM 或 PBM,它可以是二进制格式标志 ( CV_IMWRITE_PXM_BINARY )、0 或 1。默认值为 1。

如果我们阅读以下句子普通英语,我们有一个选项列表:CV_IMWRITE_PXM_BINARY, 0 或 1。没有提到这些可以而且实际上应该结合起来!我必须进行一些实验(我还需要为我的项目存储 8 位图像),最终得到了所需的解决方案:

std::vector<int> compression_params; // Stores the compression parameters

compression_params.push_back(CV_IMWRITE_PXM_BINARY); // Set to PXM compression
compression_params.push_back(0); // Set type of PXM in our case PGM
const std::string imageFilename = "myPGM.pgm"; // Some file name - C++ requires an std::string

cv::imwrite(imageFilename, myImageMatrix, compression_params); // Write matrix to file

我的调查也受到 这个问题,作者当时(也许仍然)正在努力解决同样的问题,并且还通过有关 PXM 格式的一些基本信息,您可以在此处找到。

结果(仅图像的一部分)如下所示:

P2
32 100
255
121 237  26 102  88 143  67 224 160 164 238   8 119 195 138  16 176 244  72 106  72 211 168  45 250 161  37   1  96 130  74   8
126 122 227  86 106 120 102 150 185 218 164 232 111 230 207 191  39 222 236  78 137  71 174  96 146 122 117 175  34 245   6 125
124 121 241  67 225 203 118 209 227 168 175  40  90  19 197 190  40 254  68  90  88 242 136  32 123 201  37  35  99 179 198 163
97 161 129  35  48 140 234 237  98  73 105  77 211 234  88 176 152  12  68  93 159 184 238   5 172 252  38  68 200 130 194 216
160 188  21  53  16  79  71  54 124 234  34  92 246  49   0  17 145 102  72  42 105 252  81  63 161 146  81  16  72 104  66  41
189 100 252  37  13  91  71  40 123 246  33 157  67  96  71  59  17 196  96 110 109 116 253  30  42 203  69  53  97 188  90  68
101  36  84   5  41  59  80   8 107 160 168   9 194   8  71  55 152 132 232 102  12  96 213  24 134 208   1  55  64  43  74  22
92  77  30  44 139  96  70 152 160 146 142   8  87 243  11  91  49 196 104 250  72  67 159  44 240 225  69  29  34 115  42   2
109 176 145  90 137 172  65  25 162  57 169  92 214 211  72  94 149  20 104  56  27  67 218  17 203 182   5 124 138   2 130  48
121 225  25 106  89  76  69 189  34  25 173   8 114  83  72  52 145 154  64  40  91   2 251  53 251 237  20 124  82   2 194  42 ...

这正是本例中所需要的。您可以看到顶部的“P2”标记,并且值也清楚地从 0 到 255,即每像素 8 位。

Since ffriend's answer is only partially true, I'll add some more to it (in C++). The author of this question asks explicitly for exporting to PGM (PXM file format that stores each pixel in 8 bits) and not PNG (as ffriend describes in his/her reply). The main issue here is that the official documentation for imwrite is omho not clear about this matter at all:

For PPM, PGM, or PBM, it can be a binary format flag ( CV_IMWRITE_PXM_BINARY ), 0 or 1. Default value is 1.

If we read the sentence in normal English, we have a list of options: CV_IMWRITE_PXM_BINARY, 0 or 1. There is no mention that those can and actually are supposed to be combined! I had to experiment a little bit (I also needed to store 8-bit images for my project) and finally got to the desired solution:

std::vector<int> compression_params; // Stores the compression parameters

compression_params.push_back(CV_IMWRITE_PXM_BINARY); // Set to PXM compression
compression_params.push_back(0); // Set type of PXM in our case PGM
const std::string imageFilename = "myPGM.pgm"; // Some file name - C++ requires an std::string

cv::imwrite(imageFilename, myImageMatrix, compression_params); // Write matrix to file

My investigation was also fueled by this question where the author was (maybe still is) struggling with the very same issue and also by some basic information on the PXM format, which you can find here.

The result (only part of the image) is displayed below:

P2
32 100
255
121 237  26 102  88 143  67 224 160 164 238   8 119 195 138  16 176 244  72 106  72 211 168  45 250 161  37   1  96 130  74   8
126 122 227  86 106 120 102 150 185 218 164 232 111 230 207 191  39 222 236  78 137  71 174  96 146 122 117 175  34 245   6 125
124 121 241  67 225 203 118 209 227 168 175  40  90  19 197 190  40 254  68  90  88 242 136  32 123 201  37  35  99 179 198 163
97 161 129  35  48 140 234 237  98  73 105  77 211 234  88 176 152  12  68  93 159 184 238   5 172 252  38  68 200 130 194 216
160 188  21  53  16  79  71  54 124 234  34  92 246  49   0  17 145 102  72  42 105 252  81  63 161 146  81  16  72 104  66  41
189 100 252  37  13  91  71  40 123 246  33 157  67  96  71  59  17 196  96 110 109 116 253  30  42 203  69  53  97 188  90  68
101  36  84   5  41  59  80   8 107 160 168   9 194   8  71  55 152 132 232 102  12  96 213  24 134 208   1  55  64  43  74  22
92  77  30  44 139  96  70 152 160 146 142   8  87 243  11  91  49 196 104 250  72  67 159  44 240 225  69  29  34 115  42   2
109 176 145  90 137 172  65  25 162  57 169  92 214 211  72  94 149  20 104  56  27  67 218  17 203 182   5 124 138   2 130  48
121 225  25 106  89  76  69 189  34  25 173   8 114  83  72  52 145 154  64  40  91   2 251  53 251 237  20 124  82   2 194  42 ...

Which is exactly what is required in this case. You can see the "P2" marking at the top and also the values are clearly from 0 to 255, which is exactly 8 bits per pixel.

兔姬 2024-09-13 19:24:22

阅读了大部分答案,但没有一个能满足我的要求。这是我的实现方式。

该程序将使用网络摄像头作为摄像头,并在您按“c”时单击图片 - 我们可以更改条件,然后使其在一定时间间隔后自动单击图片

# Created on Sun Aug 12 12:29:05 2018
# @author: CodersMine

import cv2

video_path = 0 # 0 internal cam, 1 external webcam
cap = cv2.VideoCapture(video_path) 
img_ctr = 0 # To Generate File Names

while(True):
    ret, frame = cap.read()
    cv2.imshow("imshow",frame)

    key = cv2.waitKey(1)

    if key==ord('q'): # Quit
        break

    if key==ord('c'): # Capture
        cv2.imshow("Captured",frame)
        flag = cv2.imwrite(f"image{img_ctr}.png", frame)
        print(f"Image Written {flag}")
        img_ctr += 1

# Release the Camera
cap.release()
cv2.destroyAllWindows()

Read most of the answers but none of them could satisfy my requirement. Here's how I implemented it.

This program will use webcam as a camera and clicks picture when you press 'c' - we can change the condition, then make it to click pictures automatically after certain interval

# Created on Sun Aug 12 12:29:05 2018
# @author: CodersMine

import cv2

video_path = 0 # 0 internal cam, 1 external webcam
cap = cv2.VideoCapture(video_path) 
img_ctr = 0 # To Generate File Names

while(True):
    ret, frame = cap.read()
    cv2.imshow("imshow",frame)

    key = cv2.waitKey(1)

    if key==ord('q'): # Quit
        break

    if key==ord('c'): # Capture
        cv2.imshow("Captured",frame)
        flag = cv2.imwrite(f"image{img_ctr}.png", frame)
        print(f"Image Written {flag}")
        img_ctr += 1

# Release the Camera
cap.release()
cv2.destroyAllWindows()
落日海湾 2024-09-13 19:24:22

如果您不需要超精确的 2 秒,那么只需在 while(1) 循环中放置 sleep(2) 或 Sleep(2000) 即可在每次抓取之前等待 2 秒,

使用 cvSaveImage() 写入图像只需将扩展名 .pgm 放在文件名,它将使用 pgm。

If you don't need superaccurate 2seconds then simply put a sleep(2) or Sleep(2000) in the while(1) loop to wait fro 2seconds before each grab,

Write images with cvSaveImage() just put the extention .pgm on the filename and it will use pgm.

陌路终见情 2024-09-13 19:24:22

我相信格式是从文件名的扩展名中选择的 - 因此假设您的 opencv 库链接到适当的库,您可以执行以下操作:(这是从记忆中得出的,可能不正确。)

CvCapture* capture = cvCaptureFromCam(0);
IplImage* frame = cvQueryFrame(capture);
while (1) {
    frame = cvQueryFrame(capture);
    cvSaveImage("foo.pgm", &frame);
    sleep(2);
}
cvReleaseImage(&frame);
cvReleaseCapture(&capture);

I believe that the format is chosen from the extension of the filename - so assuming your opencv lib's are linked against the appropriate libs you can do something like: (this is from memory, might not be correct.)

CvCapture* capture = cvCaptureFromCam(0);
IplImage* frame = cvQueryFrame(capture);
while (1) {
    frame = cvQueryFrame(capture);
    cvSaveImage("foo.pgm", &frame);
    sleep(2);
}
cvReleaseImage(&frame);
cvReleaseCapture(&capture);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文