OpenCV matrix element-wise division gives all-zero result - c++

I use OpenCV by cocoapod on iOS C++ code. When running my app, I find it works abnormally. Finally, after digging down, I can give the following reproducible sample:
{
Mat a = (Mat_<uchar>({10, 20, 30, 40, 50, 60, 70, 80})).reshape(1, 1);
Mat b = (Mat_<uchar>({4, 5, 6, 7, 8, 9, 10, 11})).reshape(1, 1);
Mat c;
divide(a, b, c);
std::cout << "hello naive " << "a=" << a << endl << "b=" << b << endl << "a/b=" << (a / b) << "c=" << c << endl;
}
{
Mat a = (Mat_<uchar>({10, 20, 30, 40, 50, 60, 70})).reshape(1, 1);
Mat b = (Mat_<uchar>({4, 5, 6, 7, 8, 9, 10})).reshape(1, 1);
Mat c;
divide(a, b, c);
std::cout << "hello naive " << "a=" << a << endl << "b=" << b << endl << "a/b=" << (a / b) << "c=" << c << endl;
}
And the result:
im_sta[a]: {size=1 x 8, type=0, empty=0, min=10.000000, max=80.000000, miu=[45], sigma=[22.9]}
im_sta[b]: {size=1 x 8, type=0, empty=0, min=4.000000, max=11.000000, miu=[7.5], sigma=[2.29]}
im_sta[a / b]: {size=1 x 8, type=0, empty=0, min=0.000000, max=0.000000, miu=[0], sigma=[0]}
hello naive a=[ 10, 20, 30, 40, 50, 60, 70, 80]
b=[ 4, 5, 6, 7, 8, 9, 10, 11]
a/b=[ 0, 0, 0, 0, 0, 0, 0, 0]c=[ 0, 0, 0, 0, 0, 0, 0, 0]
im_sta[a]: {size=1 x 7, type=0, empty=0, min=10.000000, max=70.000000, miu=[40], sigma=[20]}
im_sta[b]: {size=1 x 7, type=0, empty=0, min=4.000000, max=10.000000, miu=[7], sigma=[2]}
im_sta[a / b]: {size=1 x 7, type=0, empty=0, min=2.000000, max=7.000000, miu=[5.29], sigma=[1.67]}
hello naive a=[ 10, 20, 30, 40, 50, 60, 70]
b=[ 4, 5, 6, 7, 8, 9, 10]
a/b=[ 2, 4, 5, 6, 6, 7, 7]c=[ 2, 4, 5, 6, 6, 7, 7]
(where im_sta is some extra statistics that I printed for more details, you can ignore it as well).
As you can see, in some cases (seems that when >=8 elements), that division results in ALL-ZERO!
How can I fix it? Thanks!

I find the answer later. Thus I post it here as a self-QA, in order to help people who have the same problem as me.
Solution: Upgrade OpenCV from 4.1 to 4.3! Then it is ok!
Actually, as you can see from the photo below, OpenCV >=4.2.0 is only available as cocoapod since 3 months ago (even if now it is 4.5.0 already)... So this is a quite new fix, if you do not want to compile opencv from source code by yourself... (When I started my project (of course before 3 months ago) there was only 4.1.0)

Related

trouble debugging c++ code pointer in Visual studio

I will like to list each member of an array listed with its corresponding register address location. Here is my code
// PointerDeferenceTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int x=0, y=0;
int *px, *py;
int number[15] = {-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9};
while (x<14)
{
px = &x;
py = number+x;
cout << x+1 << ", " << px << ", " << *px << ", " << py << ", " << *py << ", " << py++ << ", " << *(py++) << ", " << *(++py) << " \n";
++x;
}
return 0;
}
Running at 64 bits getting the following unexpected result
1, 000000D7532FF874, 0, 000000D7532FF904, -1, 000000D7532FF900, -3, -1
2, 000000D7532FF874, 1, 000000D7532FF908, 0, 000000D7532FF904, -2, 0
3, 000000D7532FF874, 2, 000000D7532FF90C, 1, 000000D7532FF908, -1, 1
4, 000000D7532FF874, 3, 000000D7532FF910, 2, 000000D7532FF90C, 0, 2
5, 000000D7532FF874, 4, 000000D7532FF914, 3, 000000D7532FF910, 1, 3
6, 000000D7532FF874, 5, 000000D7532FF918, 4, 000000D7532FF914, 2, 4
7, 000000D7532FF874, 6, 000000D7532FF91C, 5, 000000D7532FF918, 3, 5
8, 000000D7532FF874, 7, 000000D7532FF920, 6, 000000D7532FF91C, 4, 6
9, 000000D7532FF874, 8, 000000D7532FF924, 7, 000000D7532FF920, 5, 7
10, 000000D7532FF874, 9, 000000D7532FF928, 8, 000000D7532FF924, 6, 8
11, 000000D7532FF874, 10, 000000D7532FF92C, 9, 000000D7532FF928, 7, 9
12, 000000D7532FF874, 11, 000000D7532FF930, 0, 000000D7532FF92C, 8, 0
13, 000000D7532FF874, 12, 000000D7532FF934, -858993460, 000000D7532FF930, 9, -858993460
14, 000000D7532FF874, 13, 000000D7532FF938, -858993460, 000000D7532FF934, 0, -858993460
I cannot figure out what I am doing wrong. The 4th column (py) is starting to list the 4th item in the array. But the code is set to read the first (number[0]).
I amusing W10 Visual studio community 2017 compile 64 bit
UPDATE 1: In response to PhoenixBlue comment. Amended the array sample to use different numbers.
UPDATE 2: This is my expected result
1, 000000D7532FF874, 0, 000000D7532FF904, -4, 000000D7532FF900, -3, -1
2, 000000D7532FF874, 1, 000000D7532FF908, -3, 000000D7532FF904, -2, 0
3, 000000D7532FF874, 2, 000000D7532FF90C, -2, 000000D7532FF908, -1, 1
4, 000000D7532FF874, 3, 000000D7532FF910, -1, 000000D7532FF90C, 0, 2
5, 000000D7532FF874, 4, 000000D7532FF914, 0, 000000D7532FF910, 1, 3
6, 000000D7532FF874, 5, 000000D7532FF918, 1, 000000D7532FF914, 2, 4
7, 000000D7532FF874, 6, 000000D7532FF91C, 2, 000000D7532FF918, 3, 5
8, 000000D7532FF874, 7, 000000D7532FF920, 3, 000000D7532FF91C, 4, 6
9, 000000D7532FF874, 8, 000000D7532FF924,4, 000000D7532FF920, 5, 7
10, 000000D7532FF874, 9, 000000D7532FF928, 5, 000000D7532FF924, 6, 8
11, 000000D7532FF874, 10, 000000D7532FF92C, 6, 000000D7532FF928, 7, 9
12, 000000D7532FF874, 11, 000000D7532FF930, 7, 000000D7532FF92C, 8, 0
13, 000000D7532FF874, 12, 000000D7532FF934, 8, 000000D7532FF930, 9, -858993460
14, 000000D7532FF874, 13, 000000D7532FF938, 9, 000000D7532FF934, 0, -858993460
This code is a problem py++ << ", " << *(py++) << ", " << *(++py).
In C++ you should not use multiple increments of the same variable in the same expression.
Rewrite your code like this
cout << x+1 << ", " << px << ", " << *px << ", " << py << ", " << *py << ", ";
cout << py++ << ", ";
cout << *(py++) << ", ";
cout << *(++py) << " \n";
That should fix some of the problems although as Msalters says you have other problems as well.
py overflows, when x==13, and so py=&number[13] before you increment it twice. That is Undefined Behavior, which may result in any outcome.
You probably will have more issues once you've fixed this, but Undefined Behavior is so severe that you cannot reason about minor bugs in the presence of UB. UB is so bad, it can appear to "travel back in time". You can't say "Foo happened before the UB, so it should be unaffected by it". Since UB can do anything, it can also change the past.

max subarray brute force method yields large sum for first array

I wrote a code for calculating the max subarray using brute force method. My code reads a number of arrays from an input file and returns the output file, which contains the max subarray and the sum value.
Everything works fine except the first max subarray on the output file always contains a really large number at the end, which gets added to the sum value. The subsequent sub-arrays don't have this problem. I've included an example at the bottom of this post.
I can't figure out where I went wrong. Any help would be greatly appreciated!
Here is the function that runs the algorithm and prints it to output file:
void a1(int a[], int size, string filename){
//run algorithm 1
int sum = a[0], start = 0, end = 0;
for (int x = 0; x < size; x++) {
int tempSum = 0;
int y = x;
while(y>=0){
tempSum += a[y];
if(tempSum>sum){
sum=tempSum;
start=y;
end=x;
}
y--;
}
}
//print results on file
ofstream output;
output.open(filename.c_str(), ios::out | ios::app);
output << "\nMax sum array: ";
for (int x = start; x <= end; x++) {
output << a[x];
if (x != end) output << ", ";
}
output << "\nMax sum value: " << sum << "\n";
output.close();
}
Here is the main file:
int main() {
int a[50];
ifstream inputFile;
string s;
stringstream ss;
string outputfile = "MSS_Results.txt";
//print title
ofstream output;
output.open(outputfile.c_str(), ios::out | ios::app);
output << "Algorithm 1:\n";
output.close();
//read file and run a1
int size;
char c;
inputFile.open("MSS_Problems.txt");
while (!inputFile.eof()) {
getline(inputFile, s);
size = 0;
ss << s;
ss >> c;
while (ss.rdbuf()->in_avail()) {
ss >> a[size];
size++;
ss >> c;
if (!ss.rdbuf()->in_avail() && c != ']') {
ss.clear();
getline(inputFile, s);
ss << s;
}
}
ss.clear();
if (size > 0) a1(a, size, outputfile);
}
inputFile.close();
return 0;
}
Example of input file:
[1, 2, 4, -1, 4, -10, 4, -19, 18, -1, -3, -4, 11, 3, -20, 19, -33, 50, 66, -22, -4, -55, 91, 100, -102, 9, 10, 19, -10, 10, 11, 11, -10, -18, 50, 90]
[12, 12, 14, -88, -1, 45, 6, 8, -33, 2, 8, -9, -33, -8, -23, -77, -89, 1, 9, 10, 92, 87]
[565, 78, 33, 9, 10, 84, 71, -4, -22, -55, -10, 76, -9, -9, -11, 76, 89, 11, 10, -33, 9]
[2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
Example of output file:
Algorithm 1:
Max sum array: 50, 66, -22, -4, -55, 91, 100, -102, 9, 10, 19, -10, 10, 11, 11, -10, -18, 50, 90, 3897136
Max sum value: 3897432
Max sum array: 1, 9, 10, 92, 87, 91
Max sum value: 290
Max sum array: 565, 78, 33, 9, 10, 84, 71, -4, -22, -55, -10, 76, -9, -9, -11, 76, 89, 11, 10, -33, 9, 87
Max sum value: 1055
Max sum array: 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 11
Max sum value: 103
As you can see, for the first array, there is a 3897136 that does not belong to the original array.
If I delete the first line from the input, the input looks like this:
[12, 12, 14, -88, -1, 45, 6, 8, -33, 2, 8, -9, -33, -8, -23, -77, -89, 1, 9, 10, 92, 87]
[565, 78, 33, 9, 10, 84, 71, -4, -22, -55, -10, 76, -9, -9, -11, 76, 89, 11, 10, -33, 9]
[2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
Now my output looks something like this:
Algorithm 1:
Max sum array: 1, 9, 10, 92, 87, 624
Max sum value: 823
Max sum array: 565, 78, 33, 9, 10, 84, 71, -4, -22, -55, -10, 76, -9, -9, -11, 76, 89, 11, 10, -33, 9, 87
Max sum value: 1055
Max sum array: 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
Max sum value: 92
I initialized the array incorrectly, which is why it sometimes gave me a garbage number at the end. To initialize properly, I simply changed
a[100];
to
a[100] = {0}
and that fixed the problem of abnormally large numbers at the end of the array.
I then moved a[100] = {0} into the while loop where the code reads the input file. That seems to have fixed the new issue of reading wrong elements into the array.
Final unresolved issue: 0 at the end of array.
Will update once I solve that.
Since all the problem is finding the maximum subarray , therefore the "large number" at the end will need to get added to produce the correct results.
In the first example that you provided, all the numbers were positive.
This means that the maximum sum subarray will actually be the sum of all the array elements.
Your algorithm part is OK;

Min, Max, Avg Filters in opencv2.4.13

Is there any built-in function to apply min, max and Avg filters to an image in opencv2.4.13 ?
I'm using c++ .
As #Miki mentioned in the comments, boxfilter is a mean filter. Just set the kernel size you want and leave normalize=true (the default).
The functions erode and dilate are min and max filters, respectively. You can create the kernel using createMorphologyFilter, create your own, or use the default 3x3 as I've done. The borders are set by default to +inf for erode and -inf for dilate so they do not contribute to the result.
int main(int argc, const char * argv[]) {
char image_data[25] = {1, 3, 8, 8, 4,
4, 2, 7, 9, 9,
1, 5, 0, 5, 9,
3, 7, 5, 2, 1,
0, 4, 7, 9, 4};
cv::Mat image = cv::Mat(5, 5, CV_8U, image_data);
std::cout << "image = " << std::endl << image << std::endl;
cv::Mat avgImage;
// Perform mean filtering on image using boxfilter
cv::boxFilter(image, avgImage, -1, cv::Size(3,3));
std::cout << "avgImage = " << std::endl << avgImage << std::endl;
cv::Mat kernel; // Use the default structuring element (kernel) for erode and dilate
cv::Mat minImage;
// Perform min filtering on image using erode
cv::erode(image, minImage, kernel);
std::cout << "minImage = " << std::endl << minImage << std::endl;
cv::Mat maxImage;
// Perform max filtering on image using dilate
cv::dilate(image, maxImage, kernel);
std::cout << "maxImage = " << std::endl << maxImage << std::endl;
return 0;
}
Here are the results:
image =
[ 1, 3, 8, 8, 4;
4, 2, 7, 9, 9;
1, 5, 0, 5, 9;
3, 7, 5, 2, 1;
0, 4, 7, 9, 4]
avgImage =
[ 3, 4, 6, 8, 8;
3, 3, 5, 7, 7;
4, 4, 5, 5, 6;
4, 4, 5, 5, 5;
5, 5, 5, 4, 4]
minImage =
[ 1, 1, 2, 4, 4;
1, 0, 0, 0, 4;
1, 0, 0, 0, 1;
0, 0, 0, 0, 1;
0, 0, 2, 1, 1]
maxImage =
[ 4, 8, 9, 9, 9;
5, 8, 9, 9, 9;
7, 7, 9, 9, 9;
7, 7, 9, 9, 9;
7, 7, 9, 9, 9]

Matrix manipulation on MATLAB to C++ or OpenCV

I'm trying to do this operation in C++, but I cant wrap my head around it.
I tried looking in http://mathworks.com/help/matlab/ref/image.html but I still don't get it.
im is a matrix in Matlab. Width is 640
im(:,Width+(1:2),:) = im(:,1:2,:);
Is there anything similar to this operation in OpenCV Matrix or C++
Solution 1
You can use colRange function:
mat.colRange(0, 2).copyTo(mat.colRange(w, 2 + w));
Example:
//initilizes data
float data[2][4] = { { 1, 2, 3, 4}, { 5, 6, 7, 8 } };
Mat mat(2, 4, CV_32FC1, &data);
int w = 2; //w is equivelant to Width in your script, in this case I chose it to be 2
std::cout << "mat before: \n" << mat << std::endl;
mat.colRange(0, 2).copyTo(mat.colRange(w, 2 + w));
std::cout << "mat after: \n" << mat << std::endl;
Result:
mat before:
[1, 2, 3, 4;
5, 6, 7, 8]
mat after:
[1, 2, 1, 2;
5, 6, 5, 6]
Solution 2
Alternatively, use cv::Rect object, as follows:
cv::Mat roi = mat(cv::Rect(w, 0, 2, mat.rows));
mat(cv::Rect(0, 0, 2, mat.rows)).copyTo(roi);
There are several way to initialize a Rect, in my case I chose the following c-tor:
cv::Rect(int x, int y, int width, int height);
The result are the same as an in Solution 1.
Maybe you could also use Eigen that can serve the need. It has Block operations
Adapting the example provided under link you would need smth like:
Eigen::MatrixXf m(4, 4);
m << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16;
cout <<"original matrix \n" << m << endl;
m.block<2, 2>(1, 1) = m.block<2, 2>(2, 2);
cout <<"modified matrix \n" << m << endl;
Output:
original matrix
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
modified matrix
1 2 3 4
5 11 12 8
9 15 16 12
13 14 15 16

invalid conversion from 'const int*' to 'int' [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
this is C++
[Error] invalid conversion from 'const int*' to 'int' [-fpermissive]
void boite(int ligne,int colonne,int i,int s[],int k)
{
int n;
n= s_boite[i][ligne][colonne]; // i numero de la boite
for(;n!=0;n/=2)
s[k--]=n%2;
}
more additions : s_boit
static const int s_boite[8][4][16] = { { {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7}, { 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8}, { 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0}, {15, 12, 8, 2, 4, 9, 1, 7, 5, ...ext
the call for this function :
for(i=0;i<8;i++) // appeller les boittes
{
ligne = resultat[i][0]*2 + resultat[i][5]; // le 1er et le dernier bit converit a au decimal
for(j=0;j<4;j++) // 4 bits du milieu
{colonne += resultat[i][j+1]*puiss(2,(3-j));}//acumulation en calculant la colone (traduction en decimal)
boite(ligne,colonne,i,mat,(4*(i+1)-1)); //mat pour sauvgarder le resultat
}
Here is the code (slightly modified) that is compiled without any warnings. Please check, where is the actual root cause:
#include <iostream>
static const int s_boite[1][1][16] = { { {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7}}};
void boite(int ligne,int colonne,int i,int s[],int k)
{
int n;
n= s_boite[i][ligne][colonne]; // i numero de la boite
for(;n!=0;n/=2)
s[k--]=n%2;
}
int main() {
int a[2] = {-1, -1};
boite(0,3,0,a,0);
std::cout << "a[0] = " << a[0] << std::endl; // =1
return 0;
}
I edited your source code a little bit and compiled using g++ with the -Wextra and -Wall flags. Compiles for me, got a warning because I took the 3rd dimension away. Shouldn't be relevant.
static const int s_boite[8][16] =
{
{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
{ 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
{ 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
};
void boite(int ligne,int colonne,int i,int s[],int k)
{
int n;
n= s_boite[i][ligne]; // i numero de la boite
for(;n!=0;n/=2)
s[k--]=n%2;
}
int main(void)
{
int ess[32];
boite(1, 0, 1, ess, 16);
return 0;
}