title: How to set given channel of a cv::Mat to a given value efficiently without changing other channels?
body: <p>How to set given channel of a <code>cv::Mat</code> to a given value efficiently without changing other channels? For example, I want to set its fourth channel (alpha channel) value to <code>120</code> (i.e. half transparent), something like:</p>
  <pre><code>cv::Mat mat; // with type CV_BGRA
  ...
  mat.getChannel(3) = Scalar(120); // &lt;- this is what I want to do
  </code></pre>
  <p>P.S.: My current solution is first split the <code>mat</code> into multiple channels and set the alpha channel, and then merge them back.</p>
  <p>P.S.2: I know that I can do this quickly if I also want to change other channels as well by:</p>
  <pre><code>mat.setTo(Scalar(54, 154, 65, 120)); 
  </code></pre>
  <hr />
  <h2>Update with generalized solution:</h2>
  <p>Both methods will work for setting all mat values at given channel to given value. And they will work for all matrices whether they are continuous or not.</p>
  <h3>Method-1 - more efficient</h3>
  <p>-&gt; based on @Antonio's answer and further improved by @MichaelBurdinov</p>
  <pre><code>// set all mat values at given channel to given value
  void setChannel(Mat &amp;mat, unsigned int channel, unsigned char value)
  {
      // make sure have enough channels
      if (mat.channels() &lt; channel + 1)
          return;
  
      const int cols = mat.cols;
      const int step = mat.channels();
      const int rows = mat.rows;
      for (int y = 0; y &lt; rows; y++) {
          // get pointer to the first byte to be changed in this row
          unsigned char *p_row = mat.ptr(y) + channel; 
          unsigned char *row_end = p_row + cols*step;
          for (; p_row != row_end; p_row += step)
              *p_row = value;
      }
  }
  </code></pre>
  <h3>Method-2 - more elegant</h3>
  <p>-&gt; based on @MichaelBurdinov's answer</p>
  <pre><code>// set all mat values at given channel to given value
  void setChannel(Mat &amp;mat, unsigned int channel, unsigned char value)
  {
      // make sure have enough channels
      if (mat.channels() &lt; channel+1)
          return;
  
      // check mat is continuous or not
      if (mat.isContinuous())
          mat.reshape(1, mat.rows*mat.cols).col(channel).setTo(Scalar(value));
      else{
          for (int i = 0; i &lt; mat.rows; i++)
              mat.row(i).reshape(1, mat.cols).col(channel).setTo(Scalar(value));
      }
  }
  </code></pre>
  <hr />
  <p><strong>P.S.:</strong> It's worthy noting that, according to the <a href="http://docs.opencv.org/modules/core/doc/basic_structures.html#mat-iscontinuous" rel="noreferrer">documentation</a>, matrices created with <code>Mat::create()</code> are always continuous. But if you extract a part of the matrix using <code>Mat::col()</code>, <code>Mat::diag()</code>, and so on, or constructed a matrix header for externally allocated data, such matrices may no longer have this property.</p>