<h5 dir="auto">System information (version)</h5>
<p dir="auto">reproduced in linux (redhat 7.5 and ubuntu 16) on both intel and power architectures, on opencv versions 3.1 and 3.2<br>
via the standard python binding of opencv</p>
<h3 dir="auto">problem description</h3>
<p dir="auto">warpAffine (and possibly other functions) use very incorrect constant border value when the image has more than 4 channels.</p>
<h3 dir="auto">reproducing the problem:</h3>
<p dir="auto">I've created a minimalistic self contained script to easily reproduce the problem:</p>
<p dir="auto"><a href="https://gist.github.com/YoelShoshan/1c9976eb82b00fa27f0b0491c6093efc">https://gist.github.com/YoelShoshan/1c9976eb82b00fa27f0b0491c6093efc</a></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="import cv2
import numpy as np

def base_tens_stats(tens):
    print(f'shape={tens.shape} min={tens.min()} mean={tens.mean()} max={tens.max()}')

x = np.random.randint(0,1020, (256,256,20)).astype(np.uint16)

base_tens_stats(x)

M = np.array([[ -9.86677170e-01,  -3.59121144e-01,   4.28262177e+02],
       [  3.59121144e-01,  -9.86677170e-01,   3.36327148e+02],
       [  0.00000000e+00,   0.00000000e+00,   1.00000000e+00]], dtype=np.float32)

y = cv2.warpAffine(x, M[:2,:],  x.shape[:2],
                                   borderMode=cv2.BORDER_CONSTANT,
                                   borderValue=0,
                                   flags=cv2.INTER_NEAREST)

print('after transform 1')
base_tens_stats(y)

y = cv2.warpAffine(x, M[:2,:],  x.shape[:2],
                                   borderMode=cv2.BORDER_CONSTANT,
                                   borderValue=0,
                                   flags=cv2.INTER_LINEAR)

print('after transform 2')
base_tens_stats(y)"><pre class="notranslate"><code class="notranslate">import cv2
import numpy as np

def base_tens_stats(tens):
    print(f'shape={tens.shape} min={tens.min()} mean={tens.mean()} max={tens.max()}')

x = np.random.randint(0,1020, (256,256,20)).astype(np.uint16)

base_tens_stats(x)

M = np.array([[ -9.86677170e-01,  -3.59121144e-01,   4.28262177e+02],
       [  3.59121144e-01,  -9.86677170e-01,   3.36327148e+02],
       [  0.00000000e+00,   0.00000000e+00,   1.00000000e+00]], dtype=np.float32)

y = cv2.warpAffine(x, M[:2,:],  x.shape[:2],
                                   borderMode=cv2.BORDER_CONSTANT,
                                   borderValue=0,
                                   flags=cv2.INTER_NEAREST)

print('after transform 1')
base_tens_stats(y)

y = cv2.warpAffine(x, M[:2,:],  x.shape[:2],
                                   borderMode=cv2.BORDER_CONSTANT,
                                   borderValue=0,
                                   flags=cv2.INTER_LINEAR)

print('after transform 2')
base_tens_stats(y)
</code></pre></div>
<p dir="auto">here's an example output:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="shape=(256, 256, 20) min=0 mean=509.25673599243163 max=1019
after transform 1
shape=(256, 256, 20) min=0 mean=10139.467961883545 max=62814
after transform 2
shape=(256, 256, 20) min=0 mean=138.16527404785157 max=1019"><pre class="notranslate"><code class="notranslate">shape=(256, 256, 20) min=0 mean=509.25673599243163 max=1019
after transform 1
shape=(256, 256, 20) min=0 mean=10139.467961883545 max=62814
after transform 2
shape=(256, 256, 20) min=0 mean=138.16527404785157 max=1019
</code></pre></div>
<h3 dir="auto">expected result</h3>
<p dir="auto">the printed "all max=..."  should be max=1019, but instead it gets filled with value 62814 when the channels num is bigger than 4 !</p>
<h5 dir="auto">System information (version)</h5>
<ul dir="auto">
<li>OpenCV =&gt; 3.2</li>
<li>Operating System / Platform =&gt; ubuntu 14.04</li>
<li>Compiler =&gt; GCC 4.8.2</li>
</ul>
<h5 dir="auto">Detailed description</h5>
<p dir="auto">When using warpPerspective with images with more than 4 channels, using BORDER_CONSTANT and one of the interpolation methods INTER_NEAREST, INTER_CUBIC or INTER_LANCZOS4, the borders are wrong.</p>
<h5 dir="auto">Steps to reproduce</h5>
<p dir="auto">Call the following function using BORDER_CONSTANT and one of the interpolation methods above, pass at least one grayscale image and a nonunit transform:</p>
<div class="highlight highlight-source-c++ notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="void test(const std::vector&lt;cv::Mat&gt; &amp;src_images, const cv::Matx33d &amp;transform,
          cv::Size img_size, int num_channels = 100, int interpolation = cv::INTER_NEAREST, 
          int border = cv::BORDER_CONSTANT, const cv::Scalar &amp;value = cv::Scalar(255, 170, 85, 0))
{
    std::vector&lt;cv::Mat&gt; channels(num_channels), channels_true(num_channels);

    for (int i = 0; i &lt; num_channels; ++i) {
        int num = std::rand() % src_images.size();
        channels[i] = src_images[num].clone();
        channels_true[i] = channels[i].clone();
    }
    cv::Mat multichannel;
    cv::merge(channels, multichannel);

    for (size_t i = 0; i &lt; channels_true.size(); ++i) {
        cv::Scalar val = value[i % 4];
        auto ch = channels_true[i];
        cv::warpPerspective(ch, ch, transform, img_size, interpolation, border,
                            val);
    }
    cv::warpPerspective(multichannel, multichannel, transform,
                    img_size, interpolation, border, value);
    cv::split(multichannel, channels);
    for (size_t i = 0; i &lt; channels.size(); ++i) {
        double s = cv::sum(channels[i] != channels_true[i])[0];
        if (s &gt; 0.0) {
            cv::imshow(&quot;Error&quot;, channels[i]);
            cv::imshow(&quot;Should be&quot;, channels_true[i]);
            cv::waitKey(0);
        }
    }
}"><pre class="notranslate"><span class="pl-k">void</span> <span class="pl-en">test</span>(<span class="pl-k">const</span> std::vector&lt;cv::Mat&gt; &amp;src_images, <span class="pl-k">const</span> cv::Matx33d &amp;transform,
          cv::<span class="pl-c1">Size</span> img_size, <span class="pl-k">int</span> num_channels = <span class="pl-c1">100</span>, <span class="pl-k">int</span> interpolation = cv::INTER_NEAREST, 
          <span class="pl-k">int</span> border = cv::BORDER_CONSTANT, <span class="pl-k">const</span> cv::Scalar &amp;value = cv::Scalar(<span class="pl-c1">255</span>, <span class="pl-c1">170</span>, <span class="pl-c1">85</span>, <span class="pl-c1">0</span>))
{
    std::vector&lt;cv::Mat&gt; <span class="pl-c1">channels</span>(num_channels), <span class="pl-c1">channels_true</span>(num_channels);

    <span class="pl-k">for</span> (<span class="pl-k">int</span> i = <span class="pl-c1">0</span>; i &lt; num_channels; ++i) {
        <span class="pl-k">int</span> num = <span class="pl-c1">std::rand</span>() % src_images.<span class="pl-c1">size</span>();
        channels[i] = src_images[num].<span class="pl-c1">clone</span>();
        channels_true[i] = channels[i].<span class="pl-c1">clone</span>();
    }
    cv::Mat multichannel;
    <span class="pl-c1">cv::merge</span>(channels, multichannel);

    <span class="pl-k">for</span> (<span class="pl-c1">size_t</span> i = <span class="pl-c1">0</span>; i &lt; channels_true.<span class="pl-c1">size</span>(); ++i) {
        cv::Scalar val = value[i % <span class="pl-c1">4</span>];
        <span class="pl-k">auto</span> ch = channels_true[i];
        <span class="pl-c1">cv::warpPerspective</span>(ch, ch, transform, img_size, interpolation, border,
                            val);
    }
    <span class="pl-c1">cv::warpPerspective</span>(multichannel, multichannel, transform,
                    img_size, interpolation, border, value);
    <span class="pl-c1">cv::split</span>(multichannel, channels);
    <span class="pl-k">for</span> (<span class="pl-c1">size_t</span> i = <span class="pl-c1">0</span>; i &lt; channels.<span class="pl-c1">size</span>(); ++i) {
        <span class="pl-k">double</span> s = <span class="pl-c1">cv::sum</span>(channels[i] != channels_true[i])[<span class="pl-c1">0</span>];
        <span class="pl-k">if</span> (s &gt; <span class="pl-c1">0.0</span>) {
            <span class="pl-c1">cv::imshow</span>(<span class="pl-s"><span class="pl-pds">"</span>Error<span class="pl-pds">"</span></span>, channels[i]);
            <span class="pl-c1">cv::imshow</span>(<span class="pl-s"><span class="pl-pds">"</span>Should be<span class="pl-pds">"</span></span>, channels_true[i]);
            <span class="pl-c1">cv::waitKey</span>(<span class="pl-c1">0</span>);
        }
    }
}</pre></div>