Hafiz.M.Usman
Hafiz.M.Usman

Reputation: 231

Linear Color Gradient in openCV

i am trying to create gradient of two colors like Photoshop. r,g,b of two colors is input and result will be the Mat of gradient. I tried it like for 5 hours at least and i could not find exact effect as of the Photoshop. I tried to create my own formula (as i could not find any on the web), by changing RGB to HSV and then adding the difference of hue, with respect to the total number of rows, to each row of Mat with and also decreasing intensity to the center of image and then increasing it again. The code is self explanatory.

Additionally if anyone can tell me the exact formula for creating a gradient it will be really helpful.

here is how Photoshop gradient looks like

enter image description here

and this is what i get from my codeenter image description here

 int r1, g1, b1, r2, g2, b2;

 r1 = 255;
 g1 = 0;
 b1 = 0;
 r2 = 0;
 g2 = 255;
 b2 = 0;

 Mat input = imread("img.jpg");
 Mat color1(input.size(), input.type());
 Mat color2(input.size(), input.type());

 vector<Mat> bgr1;
 vector<Mat> bgr2;

 split(color1, bgr1);
 bgr1[0] = b1;
 bgr1[1] = g1;
 bgr1[2] = r1;
 merge(bgr1, color1);

 split(color2, bgr2);
 bgr2[0] = b2;
 bgr2[1] = g2;
 bgr2[2] = r2;
 merge(bgr2, color2);

 vector<Mat> hls1;
 vector<Mat> hls2;

 cvtColor(color1, color1, CV_BGRA2BGR);
 cvtColor(color1, color1, CV_BGR2HSV);
 split(color1, hls1);

 cvtColor(color2, color2, CV_BGRA2BGR);
 cvtColor(color2, color2, CV_BGR2HSV);
 split(color2, hls2);

 double h1 = hls1[0].at<uchar>(0, 0);
 double h2 = hls2[0].at<uchar>(0, 0);
 double dif = (h2 - h1) / input.rows;
 double h = h1;

 double halfL = 255 / 2;
 double halfR = input.rows / 2;
 double ldif = halfL / halfR;
 double l = 255;
 bool isHalf = false;

 for (int i = 0; i < input.rows; i++)
 {
  for (int j = 0; j < input.cols; j++)
  {
   hls1[0].at<uchar>(i, j) = h;
   hls1[2].at<uchar>(i, j) = l;
  }


  if (isHalf == false){
   l -= ldif;
  }
  else{
   l += ldif;
  }

  if (i < input.rows * 0.40)
  {
   h += dif * 0.40;
  }
  else if (i < input.rows * 0.60)
  {
   h += dif * 3;
  }
  else
  {
   h += dif * 0.40;
  }

  if (i >= input.rows / 2)
  {
   isHalf = true;
  }
 }

 merge(hls1, color1);
 merge(hls2, color2);

 cvtColor(color1, color1, CV_HSV2BGR);
 cvtColor(color1, color1, CV_BGR2BGRA);

 cvtColor(color2, color2, CV_HSV2BGR);
 cvtColor(color2, color2, CV_BGR2BGRA);

 namedWindow("Color1", cv::WINDOW_NORMAL);
 resizeWindow("Color1", color1.size().width / 2, color1.size().height / 2);
 imshow("Color1", color1);

 waitKey(0);
 destroyAllWindows();
 system("pause");

Upvotes: 3

Views: 8097

Answers (1)

biquette
biquette

Reputation: 226

I corrected my first code

It seems to be a really complex code for something that should be easier. I would do something like that.

int taille = 500;    
Mat image(taille,taille,CV_8UC3);
for(int y = 0; y < taille; y++){
   Vec3b val;
   val[0] = 0; val[1] = (y*255)/taille; val[2] = (taille-y)*255/taille;
   for(int x = 0; x < taille; x++)
      image.at<Vec3b>(y,x) = val;
}

On Micka's advice, I add a picture of the result with taille = 400; Result of the previous code.

Upvotes: 11

Related Questions