Premise #1: I have already solved the error, but I didn't deeply understand the cause of the compiler error.
Premise #2: The goal of this program is to copy a image into another image by a multithreaded process. Maybe a better way exists, but this is not the focus topic of the question (see premise #1).
I wrote a simple program using OpenCV 3.1 library to copy a image into another image. It takes advantage of all cores of the CPU using more threads.
The code is:
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <thread>
using namespace cv;
using namespace std;
#define IMG_PATH "..\\img\\50a.png"
void copy_image(const Mat& input, Mat& output, int row_offset, int skip_row)
{
cout << row_offset;
Size size = input.size();
for (int r = row_offset; r < size.height; r += skip_row)
{
for (int c = 0; c < size.width; c++)
{
output.at<Vec3b>(r, c) = input.at<Vec3b>(r, c);
}
}
}
int main()
{
Mat input_img = imread(IMG_PATH);
Mat output_img = Mat(input_img.size(), input_img.type()); output_img.setTo(255);
vector<thread> threads;
int thread_number = thread::hardware_concurrency();
for (int i = 0; i < thread_number; i++)
{
cout << i;
auto var = [=]()
{
return copy_image(input_img, output_img, i, thread_number);
};
threads.push_back(thread(var));
}
for (auto& thread : threads)
thread.join();
imshow("output_img", output_img);
imwrite("result.png", output_img);
waitKey(0);
}
The compiler returns me this error
Error C2664 'void copy_image(const cv::Mat &,cv::Mat &,int,int)': cannot convert argument 2 from 'const cv::Mat' to 'cv::Mat &'
that it reffers this line of code:
return copy_image(input_img, output_img, i, thread_number);
I solved this error replacing this line
auto var = [=]()
with this
auto var = [=, &input_img, &output_img]()
but actually I don't deeply understand why I received that error.
By default, variables are captured by const value . This means when the lambda is created, the lambda captures a constant copy of the outer scope variable, which means that the lambda is not allowed to modify them. In the following example, we capture the variable ammo and try to decrement it.
Capturing Local Variables by value inside Lambda Function To capture the local variables by value, specify their name in capture list i.e. }; // Local Variables std::string msg = "Hello"; int counter = 10; // Defining Lambda function and // Capturing Local variables by Value auto func = [msg, counter] () { //... };
constexpr lambda expressions in C++ Visual Studio 2017 version 15.3 and later (available in /std:c++17 mode and later): A lambda expression may be declared as constexpr or used in a constant expression when the initialization of each data member that it captures or introduces is allowed within a constant expression.
A lambda is a syntax for creating a class. Capturing a variable means that variable is passed to the constructor for that class. A lambda can specify whether it's passed by reference or by value.
If you do a capture by value in a lambda, you will get a 'member' which gets stored. As the default operator()
is a const function, you cannot modify them.
Lambdas can be defined as []() mutable {}
to allow you to modify the local variables.
By capturing the value by reference, you have something which behaves like a const pointer to a non-const object, so without the mutable, you can adapt those objects. (Unless they already where const)
Captured variables are indeed const
in the scope of the lamba:
[foo]()
{
// foo, whatever that is, is const
}
In a mutable lambda, the captured variables are not constant:
[foo]()
mutable {
// Lambda can modify foo, but it's a copy of the original
// captured variable
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With