Outils pour utilisateurs

Outils du site


diy:projets:chromakey

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
diy:projets:chromakey [2018/06/25 09:03] – [Sources du projet] sduranddiy:projets:chromakey [2018/07/02 09:35] (Version actuelle) – [Sources du projet] sdurand
Ligne 314: Ligne 314:
 === "Émetteur" === === "Émetteur" ===
    
-   #include <iostream> +<code C++> 
-   #include <chrono> +#include <iostream> 
-   #include <opencv2/opencv.hpp> +#include <chrono> 
-   #include <omp.h> +#include <opencv2/opencv.hpp> 
-    +#include <omp.h>
-    +
-   #define WIDTH 1280 +
-   #define HEIGHT 720 +
-   #define FRAME_SIZE WIDTH*HEIGHT*3 +
-   #define NUMBER_OF_FRAMES 150 +
-    +
-   #define ALL_GOOD 0 +
-   #define INVALID_ARGUMENTS -1 +
-   #define INVALID_IMAGE -2 +
-    +
-    +
-   // For a bit of comfort +
-   using namespace cv; +
-    +
-   // Simple function to test if a channel of a pixel (B, G or R) is within the interval [value - offset; value       + offset] +
-   inline bool inBounds(int value, int bound, int offset) { +
-    return abs(value - bound) <= offset; +
-   } +
-    +
-    +
-   // Most important part of the code: +
-   // Replaces the pixels of the frame close enough (depending of the offset) to the color B, G, R +
-   inline void chromakey(Mat& frame, int B, int G, int R, int offset, const Mat& background) { +
-    // Using openMP was definitely worth on a Raspberry Pi 3 model B +
-    #pragma omp parallel for +
-    // Iterating on the rows of our frame +
-    for(int i = 0; i < frame.rows; i++) { +
-    // Using a pointer to the rows is the fastest way to access a matrix +
-    Vec3b *Fi = frame.ptr<Vec3b>(i); +
-    const Vec3b *Bi = background.ptr<Vec3b>(i); +
-     +
-    // Iterating on the elements of each row +
-    for(int j = 0; j < frame.cols; j++) { +
-        // If the pixel (i, j) of our frame is close enough to B, G and R, we replace it with    the color of the background (i, j) pixel +
-    if(inBounds(Fi[j][0], B, offset) && inBounds(Fi[j][1], G, offset) &&    inBounds(Fi[j][2], R, offset)) { +
-    for(int k = 0; k < 3; k++) {  +
-     Fi[j][k] = Bi[j][k]; +
-    } +
-    } +
-    } +
-    } +
-   } +
-    +
-    +
-   int main(int argc, char** argv) { +
-    // Just a simple parameters check +
-    if(argc !=  6) { +
-     std::cerr << "Usage: ./chrk R G B offset /path/to/background_image" << std::endl; +
-    +
-     return INVALID_ARGUMENTS; +
-    } +
-    +
-    // This Mat contains our background +
-    Mat background; +
-    background = imread(argv[5]); +
-    +
-    // Testing that the images size is the same as defined +
-    // We could also just reshape the image, it would be a bit less restrictive +
-    if(!background.data || background.cols != WIDTH || background.rows != HEIGHT) { +
-     std::cerr << "ERROR: Invalid background image" << std::endl; +
-    +
-    return INVALID_IMAGE; +
-    } +
-    +
-    int B, G, R, offset; +
-    +
-    // Getting the parameters from the command line +
-    std::istringstream rr(argv[1]); +
-    std::istringstream rg(argv[2]); +
-    std::istringstream rb(argv[3]); +
-    std::istringstream rt(argv[4]); +
-    +
-    rb >> B; +
-    rg >> G; +
-    rr >> R; +
-    rt >> offset; +
-    +
-    // This Mat will contain the images +
-    Mat frame;+
  
-    // Initializing the capture, should be equivalent to:  
-    // VideoCapture cam(0); 
-    VideoCapture cam(0); 
-    
-    // Setting the width and height of the capture as defined 
-    // If not set, default resolution is 640*480 
-    cam.set(3, WIDTH); 
-    cam.set(4, HEIGHT);  
-    
-    // Adding the OpenCV JPEG parameters to a vector, this is used to encode a Mat with non-default    settings 
-    std::vector<int> jpg_parameters; 
-    jpg_parameters.push_back(CV_IMWRITE_JPEG_QUALITY); 
-    jpg_parameters.push_back(75); 
-    
-    std::vector<uchar> buffer;  
-    
-       for(int frame_count = 0; frame_count < NUMBER_OF_FRAMES; frame_count++) { 
-    const auto start = std::chrono::high_resolution_clock::now(); 
-    
-    do { 
-     cam >> frame; 
-    } while(frame.empty()); 
-    
-    chromakey(frame, B, G, R, offset, background); 
  
-    // Encoding the frame +#define WIDTH 1280 
-    imencode(".jpg", frame, buffer, jpg_parameters); +#define HEIGHT 720 
-    const unsigned int size = buffer.size(); +#define FRAME_SIZE WIDTH*HEIGHT*3 
-    +#define NUMBER_OF_FRAMES 150 
-    // Writing the encoded image to stdout + 
-    // unsigned int and uchar size are the same on ARM and 64 bits regular computer +#define ALL_GOOD 0 
-    fwrite(&size, sizeof(unsigned int), 1, stdout); +#define INVALID_ARGUMENTS -1 
-    fwrite(buffer.data(), sizeof(uchar), size, stdout); +#define INVALID_IMAGE -2 
-    + 
-    // We use stderr to print an FPS counter and not because we are already writing images on    stdout + 
-    const std::chrono::duration<float> elapsed = std::chrono::high_resolution_clock::now() - start; +// For a bit of comfort 
-    +using namespace cv; 
-    std::cerr << "\rFPS: " << 1/elapsed.count(); + 
-    +// Simple function to test if a channel of a pixel (B, G or R) is within the interval [value - offset; value + offset] 
-    std::cerr << std::endl; +inline bool inBounds(int value, int bound, int offset) { 
-    + return abs(value - bound) <= offset; 
-    return ALL_GOOD; +
-   + 
 + 
 +// Most important part of the code: 
 +// Replaces the pixels of the frame close enough (depending of the offset) to the color B, G, R 
 +inline void chromakey(Mat& frame, int B, int G, int R, int offset, const Mat& background) { 
 + // Using openMP was definitely worth on a Raspberry Pi 3 model B 
 + #pragma omp parallel for 
 + // Iterating on the rows of our frame 
 + for(int i = 0; i < frame.rows; i++) { 
 + // Using a pointer to the rows is the fastest way to access a matrix 
 + Vec3b *Fi = frame.ptr<Vec3b>(i); 
 + const Vec3b *Bi = background.ptr<Vec3b>(i); 
 +  
 + // Iterating on the elements of each row 
 + for(int j = 0; j < frame.cols; j++) { 
 + // If the pixel (i, j) of our frame is close enough to B, G and R, we replace it with the color of the background (i, j) pixel 
 + if(inBounds(Fi[j][0], B, offset) && inBounds(Fi[j][1], G, offset) && inBounds(Fi[j][2], R, offset)) { 
 + for(int k = 0; k < 3; k++) {  
 + Fi[j][k] = Bi[j][k]; 
 +
 +
 +
 +
 +
 + 
 + 
 +int main(int argc, char** argv) { 
 + // Just a simple parameters check 
 + if(argc !=  6) { 
 + std::cerr << "Usage: ./chrk R G B offset /path/to/background_image" << std::endl; 
 + 
 + return INVALID_ARGUMENTS; 
 +
 + 
 + // This Mat contains our background 
 + Mat background; 
 + background = imread(argv[5]); 
 + 
 + // Testing that the images size is the same as defined 
 + // We could also just reshape the image, it would be a bit less restrictive 
 + if(!background.data || background.cols != WIDTH || background.rows != HEIGHT) { 
 + std::cerr << "ERROR: Invalid background image" << std::endl; 
 + 
 + return INVALID_IMAGE; 
 +
 + 
 + int B, G, R, offset; 
 + 
 + // Getting the parameters from the command line 
 + std::istringstream rr(argv[1]); 
 + std::istringstream rg(argv[2]); 
 + std::istringstream rb(argv[3]); 
 + std::istringstream rt(argv[4]); 
 + 
 + rb >> B; 
 + rg >> G; 
 + rr >> R; 
 + rt >> offset; 
 + 
 + // This Mat will contain the images 
 + Mat frame; 
 + 
 + // Initializing the capture, should be equivalent to:  
 + // VideoCapture cam(0); 
 + VideoCapture cam(0); 
 + 
 + // Setting the width and height of the capture as defined 
 + // If not set, default resolution is 640*480 
 + cam.set(3, WIDTH); 
 + cam.set(4, HEIGHT);  
 + 
 + // Adding the OpenCV JPEG parameters to a vector, this is used to encode a Mat with non-default settings 
 + std::vector<int> jpg_parameters; 
 + jpg_parameters.push_back(CV_IMWRITE_JPEG_QUALITY); 
 + jpg_parameters.push_back(75); 
 + 
 + std::vector<uchar> buffer;  
 + 
 + for(int frame_count = 0; frame_count < NUMBER_OF_FRAMES; frame_count++) { 
 + const auto start = std::chrono::high_resolution_clock::now(); 
 + 
 + do { 
 + cam >> frame; 
 + } while(frame.empty()); 
 + 
 + chromakey(frame, B, G, R, offset, background); 
 + 
 + // Encoding the frame 
 + imencode(".jpg", frame, buffer, jpg_parameters); 
 + const unsigned int size = buffer.size(); 
 + 
 + // Writing the encoded image to stdout 
 + // unsigned int and uchar size are the same on ARM and 64 bits regular computer 
 + fwrite(&size, sizeof(unsigned int), 1, stdout); 
 + fwrite(buffer.data(), sizeof(uchar), size, stdout); 
 + 
 + // We use stderr to print an FPS counter and not because we are already writing images on stdout 
 + const std::chrono::duration<float> elapsed = std::chrono::high_resolution_clock::now() - start; 
 + 
 + std::cerr << "\rFPS: " << 1/elapsed.count(); 
 +
 + std::cerr << std::endl; 
 + 
 + return ALL_GOOD; 
 + 
 +</code>
  
 === "Récepteur" === === "Récepteur" ===
  
 +<code C++>
 +#include <iostream>
 +#include <chrono>
 +#include <opencv2/opencv.hpp>
 +
 +// WIDTH, HEIGHT and NUMBER_OF_FRAMES should always be set to the same value as in the transmitter
 +#define WIDTH 1280
 +#define HEIGHT 720
 +// Maximum size of the received frame
 +// In theory, if jpeg doesn't compress the image at all, it could be larger than that because of the format overhead
 +// I'm not sure it can ever happen, so, as this program should not be used for critical stuff (it really should not), I'm just gonna assume it won't happen
 +#define FRAME_SIZE WIDTH*HEIGHT*3 
 +#define NUMBER_OF_FRAMES 150
 +
 +#define ALL_GOOD 0
 +
 +
 +
 +int main(int argc, char **argv) {
 + // Actual size of the received frame
 + unsigned int size; 
 + uchar buffer[FRAME_SIZE];
 + cv::Mat frame;
 +
 + for(int frame_count = 0; frame_count < NUMBER_OF_FRAMES; frame_count++) {
 + // Reading the encoded image from stdin
 + // unsigned int and uchar size are the same on ARM and 64 bits regular computer
 + fread(&size, sizeof(unsigned int), 1, stdin);
 + fread(buffer, sizeof(uchar), size, stdin);
 +
 + std::vector<uchar> data(buffer, buffer+size);
 +
 + // Decoding the received frame
 + frame = cv::imdecode(cv::Mat(data), cv::IMREAD_UNCHANGED);
 +
 + // Displaying the received frame
 + cv::imshow("frame", frame);
 +
 + // This wait is mandatory for the image to actually display
 + cv::waitKey(1);
 + }
 +
 + return ALL_GOOD;
 +}
 +</code>
  
 ---- ----
-//Auteur: Sylvain D//+//Auteur: S. Durand//
diy/projets/chromakey.1529917411.txt.gz · Dernière modification : 2018/06/25 09:03 de sdurand