I wanted the values of the given ColumnVector to be right-shifted and copied to another RowVector that is larger than ColumnVector by one elemnt. I wanted to accomplish this by copying columnVector to a certain range within RowVector.
// The given columnVector ( this code snippet is added to make the error reproducable)
int yDimLen = 26; // arbitrary value
cv::Mat columnVector(yDimLen, 1, CV_32SC1, cv::Scalar(13)); // one column AND yDimLen rows
for (int r = 0; r < yDimLen; r++) // chech the values
{
printf("%d\t", *(columnVector.ptr<int>(r)));
}
// Copy elemnets of columnVector to rowVector starting from column number 1
cv::Mat rowVector(1, yDimLen + 1, CV_32SC1, cv::Scalar(0));
cv::Mat rowVector_rangeHeader = rowVector.colRange(cv::Range(1, yDimLen + 1)); // header matrix, 1 in included AND (yDimLen + 1) is excluded
columnVector.copyTo(rowVector_rangeHeader);
// check the values
printf("\n---------------------------------\n");
for (int c = 0; c < yDimLen; c++)
{
printf("%d\t", rowVector_rangeHeader.ptr<int>(0)[c]); // displays 13
}
printf("\n---------------------------------\n");
for (int c = 0; c < yDimLen + 1; c++)
{
printf("%d\t", rowVector.ptr<int>(0)[c]); // displays 0 !!!
}
Doesn't the header matrix point to the same memory address that contains rowVector? if not, how to copy data to certain part of a row?
From the docs of cv::Mat::copyTo
:
Before copying the data, the method invokes:
m.create(this->size(), this->type());
so that the destination matrix is reallocated if needed.
Reallocation is needed whenever the shape or data type of the destination does not match the source. In your case it's the shape. To demonstrate this, let's add some tracing around the copyTo
call:
std::cout << "Shapes involved in `copyTo`:\n";
std::cout << "Source: " << columnVector.size() << "\n";
std::cout << "Destination: " << rowVector_rangeHeader.size() << "\n";
columnVector.copyTo(rowVector_rangeHeader);
std::cout << "After the `copyTo`:\n";
std::cout << "Destination: " << rowVector_rangeHeader.size() << "\n";
Output:
Shapes involved in `copyTo`:
Source: [1 x 26]
Destination: [26 x 1]
After the `copyTo`:
Destination: [1 x 26]
The solution is simple -- reshape
the source to match the destination.
columnVector.reshape(1, 1).copyTo(rowVector_rangeHeader);
Now we get the following output:
Shapes involved in `copyTo`:
Source: [1 x 26]
Destination: [26 x 1]
After the `copyTo`:
Destination: [26 x 1]
and rowVector
contents are as follows:
[0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13]
As an alternative, you could just use std::copy
together with MatIterator
s.
std::copy(columnVector.begin<int>()
, columnVector.end<int>()
, rowVector_rangeHeader.begin<int>());
rowVector
contents are the same as before:
[0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13]