# How can I perform arithmetic operations with pixel

I have a set of 70 RGB images (argc=71). I wanted to change pixel values according to these formulas:

l1 = (R-G)^2/((R-G)^2 + (R-B)^2 + (G-B)^2);

l2 = (R-B)^2/((R-G)^2 + (R-B)^2 + (G-B)^2);

l3 = (R-G)^2/((G-B)^2 + (R-B)^2 + (G-B)^2);

And then store the new images. The code I tried using c++ is below but I keep getting this error:

SetPixels(99556,0x7fff76450000) malloc: * error for object 0x10a9ce000: pointer being freed was not allocated * set a breakpoint in malloc_error_break to debug

Can anyone help me solve this matter?

#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <sstream>
using namespace cv;
using namespace std;
int main(int agra, char** argv){
for(int k=1;k<=argc;k++){

char* imageName = argv[k];
Mat image;

uchar l1;
uchar l2;
uchar l3;

for (int i=0; i<=image.rows;i++){
for (int j=0; j<=image.cols; j++){
Vec3b intensity = image.at<Vec3b>(Point(i, j));
uchar blue = intensity.val[0];
int int_blue = (int) blue;
uchar green = intensity.val[1];
int int_green = (int) green;
uchar red = intensity.val[2];
int int_red = (int) red;

int rg = pow(int_red-int_green,2);
int rb = pow(int_red-int_blue,2);
int gb = pow(int_green - int_blue,2);

int int_l1 = rg/(rg+rb+gb);
int int_l2 = rb/(rg+rb+gb);
int int_l3 = gb/(rg+rb+gb);

l1 = (uchar) int_l1;
l2 = (uchar) int_l2;
l3 = (uchar) int_l3;

intensity.val[0] = l1;
intensity.val[1] = l2;
intensity.val[2] = l3;

image.at<Vec3b>(i,j)= intensity;

}
}

stringstream ss;
string name = "l1l2l3image_";
string type = ".jpg";
ss<<name<<(k)<<type;
string filename = ss.str();
ss.str("");
imwrite(filename, image);
}
return 0;
}

edit retag close merge delete

int int_l1 = rg/(rg+rb+gb); <-- this integer division will always be 0 ! 

( 2016-07-22 04:59:28 -0600 )edit

Sort by » oldest newest most voted
• image.at<Vec3b>(j,i)= intensity; <-- i,j , not j,i (you're probably out of bounds this way)
• please use the c++ headers: #include <opencv2/opencv.hpp> not the deprecated c ones(cv.h, highgui.h)
• in general, - try to avoid per-pixel loops.
•  pixel order is BGR in opencv, not RGB

imho, you have to do this in float space, not in 8u. while i'm at it, one could get rid of the loops, too.

void filter2 (const Mat &image, Mat &out)
{
// convert and split
Mat imgf;
image.convertTo(imgf, CV_32F, 1.0/255.0);
Mat chn[3];
split(imgf, chn);
// (R-G)^2
Mat rg = chn[2] - chn[1];
multiply(rg,rg,rg);
// (R-B)^2
Mat rb = chn[2] - chn[0];
multiply(rb,rb,rb);
// (G-B)^2
Mat gb = chn[1] - chn[0];
multiply(gb,gb,gb);
// divide by sum
Mat sm = (rg + rb + gb);
divide(rg, sm, rg);
divide(rb, sm, rb);
divide(gb, sm, gb);
// merge and concvert
Mat ch2[] = {rg, rb, gb};
merge(ch2, 3, imgf);
imgf.convertTo(out, CV_8U, 255.0);
}

int main(int agra, char** argv){
String fn="phase1.png";
if (agra>1) fn = argv[1];
if (image.empty())
{
cerr << "U$)TZ(T§$TI§H";
return 1;
}
Mat result;
filter2(image, result);
imshow("org", image);
imshow("res", result);
waitKey(0);
return 0;
}

more

Note taken on the headers (must have learnt using an old tutorial...). Regarding the question itself, I now get the written images all black, any suggestions on that? Thanks for the tips and help!

( 2016-07-21 10:11:43 -0600 )edit

That is only if I let default options on imread. If I load it unchanged the order will still be RGB, right?

( 2016-07-21 10:56:13 -0600 )edit

no, you're wrong about that. the order is always BGR. "unchanged" only means, that a possible alpha channel won't get discarded, or a 16bit img won't get converted to 8bit

( 2016-07-21 11:23:22 -0600 )edit

sidenote: you only have to calculate e.g. pow(R-G,2)`once, not 3 times.

( 2016-07-21 11:25:17 -0600 )edit

Thanks on the notes! Still can't seem to write the modified images... Is there anything more for me to correct? I have no 'error' message but still nothing happens

( 2016-07-22 04:27:36 -0600 )edit
1

Thank you so much, it solves my main goal!!

( 2016-07-26 09:28:15 -0600 )edit

Official site

GitHub

Wiki

Documentation