# Thin plate spline warpImage produces only zeros

**URL:** <https://forum.opencv.org/t/thin-plate-spline-warpimage-produces-only-zeros/1125>\
**Category:** Python\
**Tags:** shape, imgproc, contrib, thinplatespline\
**Created:** [January 25, 2021, 2:54pm UTC](https://forum.opencv.org/t/thin-plate-spline-warpimage-produces-only-zeros/1125 "2021-01-25T14:54:26Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![pakoun](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/pakoun/32/743_2.png) [@pakoun](https://forum.opencv.org/u/pakoun)\
**Post date:** [January 25, 2021, 2:54pm UTC](https://forum.opencv.org/t/thin-plate-spline-warpimage-produces-only-zeros/1125/1 "2021-01-25T14:54:26Z")

</div>

Dear all,

I am trying to warp an image using the thinplatespline but after warping, the image contains only 0 values. I am attaching a working code example and the datasets as well. I hope for some help to show me the right path again..

 ![image](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/1X/96df0c98d501ab5b9cc8487dc8cbc141164e198c.jpeg)

```python
import cv2
import numpy as np
from PIL import Image

pts1 = np.array([[[1000., 1000.], [1000., 2800.], [1000., 4600.], [1000., 6400.],
                  [1000., 7667.], [2800., 1000.], [2800., 2800.], [2800., 4600.],
                  [2800., 6400.], [2800., 7667.], [4600., 1000.], [4600., 2800.],
                  [4600., 4600.], [4600., 6400.], [4600., 7667.], [6400., 1000.],
                  [6400., 2800.], [6400., 4600.], [6400., 6400.], [6400., 7667.],
                  [7667., 1000.], [7667., 2800.], [7667., 4600.], [7667., 6400.],
                  [7667., 7667.]]])
pts2 = np.array([[[1007., 989.], [1006., 2789.], [1005., 4586.], [1005., 6386.],
                  [1002., 7653.], [2808., 989.], [2808., 2785.], [2806., 4586.],
                  [2802., 6387.], [2801., 7654.], [4605., 992.], [4598., 2792.],
                  [4595., 4590.], [4593., 6390.], [4594., 7656.], [6390., 1000.],
                  [6392., 2797.], [6388., 4597.], [6391., 6392.], [6390., 7659.],
                  [7655., 1006.], [7654., 2802.], [7654., 4600.], [7654., 6395.],
                  [7654., 7662.]]])

image = np.array(Image.open('image.jpg'))

bufferzise = 2000

imbuffer = np.zeros((image.shape[0] + bufferzise,
                    image.shape[1] + bufferzise))

imbuffer[int(1000):int(1000 + image.shape[0]),
         int(1000):int(1000 + image.shape[1])] = image[:, :]

matches = list()
for ipoint in range(0, pts1.shape[1]):
    matches.append(cv2.DMatch(ipoint, ipoint, 0))
tps = cv2.createThinPlateSplineShapeTransformer()
tps.estimateTransformation(pts2, pts1, matches)
out_img = tps.warpImage(imbuffer)

```

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [January 25, 2021, 3:41pm UTC](https://forum.opencv.org/t/thin-plate-spline-warpimage-produces-only-zeros/1125/2 "2021-01-25T15:41:04Z")

</div>

welcome.

> [@pakoun](#):
>
> the image contains only 0 values

could you point that out precisely in the picture? what do you expect to be there instead, and why should it be there?

---

<div class="post-metadata">

**Author:** ![pakoun](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/pakoun/32/743_2.png) [@pakoun](https://forum.opencv.org/u/pakoun)\
**Post date:** [January 25, 2021, 5:57pm UTC](https://forum.opencv.org/t/thin-plate-spline-warpimage-produces-only-zeros/1125/3 "2021-01-25T17:57:33Z")

</div>

Thank you for your reply, and my apologies for not being precise. The expected result is the same image but slightly moved (including the small black part of the image which is part of it). Instead the produced array (out\_img) contains only zeros no actual data. I upload also the erroneous image I get.

 ![black](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/1X/37dea807d358653f446af230c310fbe1e7acee1d.png)

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [January 25, 2021, 10:44pm UTC](https://forum.opencv.org/t/thin-plate-spline-warpimage-produces-only-zeros/1125/4 "2021-01-25T22:44:19Z")

</div>

ah, literally a black image that is black _everywhere_! it sounded like the result was somewhat more complex.

ok well without trying your code, I’d suggest instantiating the transformer using the static `create` method:

```auto
tps = cv2.createThinPlateSplineShapeTransformer.create() # or ...Transformer_create

```

see if that helps?

by the way: opencv has `imread`. spares you from using PIL, unless you want to use it. PIL loads images as RGB channel order. OpenCV loads them as BGR order (and relevant functions assume BGR order).

---

<div class="post-metadata">

**Author:** ![pakoun](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/pakoun/32/743_2.png) [@pakoun](https://forum.opencv.org/u/pakoun)\
**Post date:** [January 26, 2021, 8:34am UTC](https://forum.opencv.org/t/thin-plate-spline-warpimage-produces-only-zeros/1125/5 "2021-01-26T08:34:07Z")

</div>

Hi crackwitz and goodday, and thank you for the welcoming! I was too fast to dive in my problem i think 🙂

Some more information:  
I am using openCV version cv2. **version** : ‘3.4.1-dev’  
The .create() method does not exist, hence I have to instantiate they way I show above.  
I’ve tried the buildin function cv2.imread() as well. The behavior is the same, converts all values to a constant value of 152. I am really confused here.

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [January 26, 2021, 12:51pm UTC](https://forum.opencv.org/t/thin-plate-spline-warpimage-produces-only-zeros/1125/6 "2021-01-26T12:51:52Z")

</div>

oh, my mistake!

the python API in opencv v3.x has identifiers like `createThinPlateSplineShapeTransformer`  
the v4.x api has `ThinPlateSplineShapeTransformer.create`

you seem to have used the right identifier already and I missed that.

hm well, now it gets trickier… I hope someone else can get involved. I’m currently not set up to run most opencv modules.

it may be that _that_ code/APIs has never been tested for use with python, and some things in the bindings generation don’t work right. the docs don’t even mention the static `create` method, which makes me suspicious.

or it might all be working correctly and the issue is something else.

---

<div class="post-metadata">

**Author:** ![pakoun](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/pakoun/32/743_2.png) [@pakoun](https://forum.opencv.org/u/pakoun)\
**Post date:** [January 26, 2021, 1:00pm UTC](https://forum.opencv.org/t/thin-plate-spline-warpimage-produces-only-zeros/1125/7 "2021-01-26T13:00:45Z")

</div>

Hey thanks for your feedback. Crossing fingers that someone has faced and overcame the same issue…

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [January 26, 2021, 1:08pm UTC](https://forum.opencv.org/t/thin-plate-spline-warpimage-produces-only-zeros/1125/8 "2021-01-26T13:08:31Z")

</div>

shot in the dark: try passing `pts1` and `pts2` as `np.float32`. np.array on python floats will result in `np.float64`, which _some_ OpenCV APIs don’t expect, so this might be one of those.

same goes for your imbuffer. make sure it’s some “tame” type like float32 or uint8. specify `dtype=...` in the creation of it.

---

<div class="post-metadata">

**Author:** ![pakoun](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/pakoun/32/743_2.png) [@pakoun](https://forum.opencv.org/u/pakoun)\
**Post date:** [January 26, 2021, 4:10pm UTC](https://forum.opencv.org/t/thin-plate-spline-warpimage-produces-only-zeros/1125/9 "2021-01-26T16:10:01Z")

</div>

I did tried float32 but same result… everything is black.  
I did notice though the following.

1. Use the whole image which contains a corner with 0s. Put it within this buffered area (imbuffer) which is also 0s. Then the result is this black image. So the array contains only 0s.

2. I resampled the initial image in order to avoid the small black area at the corner, hence not to contain 0s. Following i added the buffer area, so I have a zero area around the image. The warping image is normal! Meaning that it is not black!

3. I cheated by using the initial image but replacing all 0s with 1s. Added the buffer. The results again the same; just a totally black image.

Not sure if that leads to somewhere but definitely doesn’t make sense to me.

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [January 26, 2021, 4:33pm UTC](https://forum.opencv.org/t/thin-plate-spline-warpimage-produces-only-zeros/1125/10 "2021-01-26T16:33:23Z")

</div>

if you believe it could be a bug, feel free to assemble a minimal reproducible example including all necessary data (images) and open an issue on github. you should make sure that issue is reproducible with master branch (latest 4.x) or 3.4 branch, i.e. no old versions of opencv (pre v4.5, pre v3.4)

---

<div class="post-metadata">

**Author:** ![pakoun](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/pakoun/32/743_2.png) [@pakoun](https://forum.opencv.org/u/pakoun)\
**Post date:** [January 27, 2021, 10:49am UTC](https://forum.opencv.org/t/thin-plate-spline-warpimage-produces-only-zeros/1125/11 "2021-01-27T10:49:31Z")

</div>

That’s probably a good idea, will try to prepare something as soon as I find the time. Thanks again for your time 🙂

---

<div class="post-metadata">

**Author:** ![Aleksandr\_P](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/aleksandr_p/32/1180_2.png) [@Aleksandr\_P](https://forum.opencv.org/u/Aleksandr_P)\
**Post date:** [July 19, 2021, 11:45pm UTC](https://forum.opencv.org/t/thin-plate-spline-warpimage-produces-only-zeros/1125/12 "2021-07-19T23:45:04Z")

</div>

I ran into the same issue and the reason was due to choice of points. Just try shrinking it pts2[:,:4,:], pts2[:,:4,:] and check if it’s still black – if yes, choose more spatially distanced points. With certain set of points you’ll get a black screen even if you pass same set of points twice, i.e.:  
`tps.estimateTransformation(pts, pts1, matches)`  
^ i’m not sure why it’s the case though. OpenCV 4.5.2

---

<div class="post-metadata">

**Author:** ![Lin\_Zhang](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/lin_zhang/32/13682_2.png) [@Lin\_Zhang](https://forum.opencv.org/u/Lin_Zhang)\
**Post date:** [September 4, 2025, 2:51am UTC](https://forum.opencv.org/t/thin-plate-spline-warpimage-produces-only-zeros/1125/13 "2025-09-04T02:51:07Z")

</div>

Wow, resurrecting a thread from 2021! I just hit this same wall and finally figured it out, so I wanted to share the solution.

The most annoying thing about this library is definitely how `tps.estimateTransformation` handles errors. If it can’t figure out the transformation, it just gives up and outputs a black image **without a single error message**. It took me forever to realize the function was failing and not just an issue with my image display code.

Here’s what that silent failure looks like compared to the final, working result:

[the website only allows me to attach one media in this reply, I’ll upload the comparison in a new one later]

Here’s how I managed to get it work:

1. It turns out there’s an unfixed bug in OpenCV’s `ThinPlateSpline` module that’s been there since 2017. The official documentation for `estimateTransformation` tells you the input order is `source_` **`points`** , then `target_points`.

**But the developers actually implemented it backwards.**

So for **image warping** , you have to swap them. But here’s the part that will make you want to flip a table: if you are transforming a set of floating points (and not the whole image), the documented order is suddenly correct. (Total facepalm moment, I know).

tps\_img = cv2.createThinPlateSplineShapeTransformer()  
tps\_img.estimateTransformation(target\_points, source\_points, matches)  
pts = tps\_img.warpImage(img)

tps\_pts = cv2.createThinPlateSplineShapeTransformer()  
tps\_pts.estimateTransformation(source\_points, target\_points, matches)  
pts = tps\_pts.applyTransformation(p)

It’s a known issue. You can read the whole saga on the official OpenCV issue tracker here [ThinPlateSplineShapeTransformer::wrapImage transformed X and Y values are located in the oposite side · Issue #7084 · opencv/opencv · GitHub](https://github.com/opencv/opencv/issues/7084) .

1. as mentioned before, it has to be float32. PLUS, it also matters with the reshape size.

 ![image](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/c/c5970b9ae123c5b34f46dc560a61bafa3a137a28.png)

Good luck 🙂

---

<div class="post-metadata">

**Author:** ![Lin\_Zhang](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/lin_zhang/32/13682_2.png) [@Lin\_Zhang](https://forum.opencv.org/u/Lin_Zhang)\
**Post date:** [September 4, 2025, 2:51am UTC](https://forum.opencv.org/t/thin-plate-spline-warpimage-produces-only-zeros/1125/14 "2025-09-04T02:51:53Z")

</div>

![企业微信截图_17568715772698](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/9/95c0e2e7a6df1a311f6d3decde4adc71291ade0c.jpeg)

---

<div class="post-metadata">

**Author:** ![Lin\_Zhang](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/lin_zhang/32/13682_2.png) [@Lin\_Zhang](https://forum.opencv.org/u/Lin_Zhang)\
**Post date:** [September 4, 2025, 2:52am UTC](https://forum.opencv.org/t/thin-plate-spline-warpimage-produces-only-zeros/1125/15 "2025-09-04T02:52:37Z")

</div>

![企业微信截图_17568800591972](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/7/7df76a8ac97a2e5a09ad559b2dac310af9b1a1ee.jpeg)
