Skip to content

Commit cd59516

Browse files
committed
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
2 parents 1a3a25f + bbad38b commit cd59516

File tree

12 files changed

+219
-24
lines changed

12 files changed

+219
-24
lines changed

.github/ISSUE_TEMPLATE.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
<!--
2+
If you have a question rather than reporting a bug please go to https://forum.opencv.org where you get much faster responses.
3+
If you need further assistance please read [How To Contribute](https://github.com/opencv/opencv/wiki/How_to_contribute).
4+
5+
This is a template helping you to create an issue which can be processed as quickly as possible. This is the bug reporting section for the OpenCV library.
6+
-->
7+
18
##### System information (version)
29
<!-- Example
310
- OpenCV => 4.2

doc/js_tutorials/js_setup/js_setup/js_setup.markdown

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -294,20 +294,20 @@ So, make sure [docker](https://www.docker.com/) is installed in your system and
294294
@code{.bash}
295295
git clone https://github.com/opencv/opencv.git
296296
cd opencv
297-
docker run --rm -v $(pwd):/src -u $(id -u):$(id -g) emscripten/emsdk emcmake python3 ./dev/platforms/js/build_js.py build_js
297+
docker run --rm -v $(pwd):/src -u $(id -u):$(id -g) emscripten/emsdk emcmake python3 ./platforms/js/build_js.py build_js
298298
@endcode
299299

300300
In Windows use the following PowerShell command:
301301

302302
@code{.bash}
303-
docker run --rm --workdir /src -v "$(get-location):/src" "emscripten/emsdk" emcmake python3 ./dev/platforms/js/build_js.py build_js
303+
docker run --rm --workdir /src -v "$(get-location):/src" "emscripten/emsdk" emcmake python3 ./platforms/js/build_js.py build_js
304304
@endcode
305305

306306
@warning
307307
The example uses latest version of emscripten. If the build fails you should try a version that is known to work fine which is `2.0.10` using the following command:
308308

309309
@code{.bash}
310-
docker run --rm -v $(pwd):/src -u $(id -u):$(id -g) emscripten/emsdk:2.0.10 emcmake python3 ./dev/platforms/js/build_js.py build_js
310+
docker run --rm -v $(pwd):/src -u $(id -u):$(id -g) emscripten/emsdk:2.0.10 emcmake python3 ./platforms/js/build_js.py build_js
311311
@endcode
312312

313313
### Building the documentation with Docker
@@ -331,5 +331,5 @@ docker build . -t opencv-js-doc
331331
Now run the build command again, this time using the new image and passing `--build_doc`:
332332

333333
@code{.bash}
334-
docker run --rm -v $(pwd):/src -u $(id -u):$(id -g) "opencv-js-doc" emcmake python3 ./dev/platforms/js/build_js.py build_js --build_doc
334+
docker run --rm -v $(pwd):/src -u $(id -u):$(id -g) "opencv-js-doc" emcmake python3 ./platforms/js/build_js.py build_js --build_doc
335335
@endcode

doc/py_tutorials/py_imgproc/py_pyramids/py_pyramids.markdown

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,27 +88,27 @@ B = cv.imread('orange.jpg')
8888
# generate Gaussian pyramid for A
8989
G = A.copy()
9090
gpA = [G]
91-
for i in xrange(6):
91+
for i in range(6):
9292
G = cv.pyrDown(G)
9393
gpA.append(G)
9494

9595
# generate Gaussian pyramid for B
9696
G = B.copy()
9797
gpB = [G]
98-
for i in xrange(6):
98+
for i in range(6):
9999
G = cv.pyrDown(G)
100100
gpB.append(G)
101101

102102
# generate Laplacian Pyramid for A
103103
lpA = [gpA[5]]
104-
for i in xrange(5,0,-1):
104+
for i in range(5,0,-1):
105105
GE = cv.pyrUp(gpA[i])
106106
L = cv.subtract(gpA[i-1],GE)
107107
lpA.append(L)
108108

109109
# generate Laplacian Pyramid for B
110110
lpB = [gpB[5]]
111-
for i in xrange(5,0,-1):
111+
for i in range(5,0,-1):
112112
GE = cv.pyrUp(gpB[i])
113113
L = cv.subtract(gpB[i-1],GE)
114114
lpB.append(L)
@@ -122,7 +122,7 @@ for la,lb in zip(lpA,lpB):
122122

123123
# now reconstruct
124124
ls_ = LS[0]
125-
for i in xrange(1,6):
125+
for i in range(1,6):
126126
ls_ = cv.pyrUp(ls_)
127127
ls_ = cv.add(ls_, LS[i])
128128

doc/py_tutorials/py_imgproc/py_thresholding/py_thresholding.markdown

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ ret,thresh5 = cv.threshold(img,127,255,cv.THRESH_TOZERO_INV)
4747
titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
4848
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
4949

50-
for i in xrange(6):
50+
for i in range(6):
5151
plt.subplot(2,3,i+1),plt.imshow(images[i],'gray',vmin=0,vmax=255)
5252
plt.title(titles[i])
5353
plt.xticks([]),plt.yticks([])
@@ -98,7 +98,7 @@ titles = ['Original Image', 'Global Thresholding (v = 127)',
9898
'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
9999
images = [img, th1, th2, th3]
100100

101-
for i in xrange(4):
101+
for i in range(4):
102102
plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
103103
plt.title(titles[i])
104104
plt.xticks([]),plt.yticks([])
@@ -153,7 +153,7 @@ titles = ['Original Noisy Image','Histogram','Global Thresholding (v=127)',
153153
'Original Noisy Image','Histogram',"Otsu's Thresholding",
154154
'Gaussian filtered Image','Histogram',"Otsu's Thresholding"]
155155

156-
for i in xrange(3):
156+
for i in range(3):
157157
plt.subplot(3,3,i*3+1),plt.imshow(images[i*3],'gray')
158158
plt.title(titles[i*3]), plt.xticks([]), plt.yticks([])
159159
plt.subplot(3,3,i*3+2),plt.hist(images[i*3].ravel(),256)
@@ -196,7 +196,7 @@ bins = np.arange(256)
196196
fn_min = np.inf
197197
thresh = -1
198198

199-
for i in xrange(1,256):
199+
for i in range(1,256):
200200
p1,p2 = np.hsplit(hist_norm,[i]) # probabilities
201201
q1,q2 = Q[i],Q[255]-Q[i] # cum sum of classes
202202
if q1 < 1.e-6 or q2 < 1.e-6:

doc/py_tutorials/py_imgproc/py_transforms/py_fourier_transform/py_fourier_transform.markdown

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ fft_filters = [np.fft.fft2(x) for x in filters]
268268
fft_shift = [np.fft.fftshift(y) for y in fft_filters]
269269
mag_spectrum = [np.log(np.abs(z)+1) for z in fft_shift]
270270

271-
for i in xrange(6):
271+
for i in range(6):
272272
plt.subplot(2,3,i+1),plt.imshow(mag_spectrum[i],cmap = 'gray')
273273
plt.title(filter_name[i]), plt.xticks([]), plt.yticks([])
274274

doc/py_tutorials/py_photo/py_non_local_means/py_non_local_means.markdown

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ from matplotlib import pyplot as plt
108108
cap = cv.VideoCapture('vtest.avi')
109109

110110
# create a list of first 5 frames
111-
img = [cap.read()[1] for i in xrange(5)]
111+
img = [cap.read()[1] for i in range(5)]
112112

113113
# convert all to grayscale
114114
gray = [cv.cvtColor(i, cv.COLOR_BGR2GRAY) for i in img]

modules/core/include/opencv2/core/bindings_utils.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,20 @@ String dumpString(const String& argument)
6464
return cv::format("String: %s", argument.c_str());
6565
}
6666

67+
CV_WRAP static inline
68+
String testOverloadResolution(int value, const Point& point = Point(42, 24))
69+
{
70+
return format("overload (int=%d, point=(x=%d, y=%d))", value, point.x,
71+
point.y);
72+
}
73+
74+
CV_WRAP static inline
75+
String testOverloadResolution(const Rect& rect)
76+
{
77+
return format("overload (rect=(x=%d, y=%d, w=%d, h=%d))", rect.x, rect.y,
78+
rect.width, rect.height);
79+
}
80+
6781
CV_WRAP static inline
6882
AsyncArray testAsyncArray(InputArray argument)
6983
{

modules/core/src/ocl.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3382,16 +3382,24 @@ struct Kernel::Impl
33823382
haveTempSrcUMats = true; // UMat is created on RAW memory (without proper lifetime management, even from Mat)
33833383
}
33843384

3385-
void addImage(const Image2D& image)
3385+
/// Preserve image lifetime (while it is specified as Kernel argument)
3386+
void registerImageArgument(int arg, const Image2D& image)
33863387
{
3387-
images.push_back(image);
3388+
CV_CheckGE(arg, 0, "");
3389+
CV_CheckLT(arg, (int)MAX_ARRS, "");
3390+
if (arg < (int)shadow_images.size() && shadow_images[arg].ptr() != image.ptr()) // TODO future: replace ptr => impl (more strong check)
3391+
{
3392+
CV_Check(arg, !isInProgress, "ocl::Kernel: clearing of pending Image2D arguments is not allowed");
3393+
}
3394+
shadow_images.reserve(MAX_ARRS);
3395+
shadow_images.resize(std::max(shadow_images.size(), (size_t)arg + 1));
3396+
shadow_images[arg] = image;
33883397
}
33893398

33903399
void finit(cl_event e)
33913400
{
33923401
CV_UNUSED(e);
33933402
cleanupUMats();
3394-
images.clear();
33953403
isInProgress = false;
33963404
release();
33973405
}
@@ -3416,7 +3424,7 @@ struct Kernel::Impl
34163424
bool isInProgress;
34173425
bool isAsyncRun; // true if kernel was scheduled in async mode
34183426
int nu;
3419-
std::list<Image2D> images;
3427+
std::vector<Image2D> shadow_images;
34203428
bool haveTempDstUMats;
34213429
bool haveTempSrcUMats;
34223430
};
@@ -3558,9 +3566,11 @@ int Kernel::set(int i, const void* value, size_t sz)
35583566

35593567
int Kernel::set(int i, const Image2D& image2D)
35603568
{
3561-
p->addImage(image2D);
35623569
cl_mem h = (cl_mem)image2D.ptr();
3563-
return set(i, &h, sizeof(h));
3570+
int res = set(i, &h, sizeof(h));
3571+
if (res >= 0)
3572+
p->registerImageArgument(i, image2D);
3573+
return res;
35643574
}
35653575

35663576
int Kernel::set(int i, const UMat& m)

modules/highgui/src/window_w32.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ CV_IMPL int cvInitSystem( int, char** )
249249
// check initialization status
250250
if( !wasInitialized )
251251
{
252-
// Initialize the stogare
252+
// Initialize the storage
253253
hg_windows = 0;
254254

255255
// Register the class

modules/python/src2/cv2.cpp

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
#include "opencv2/core/utils/configuration.private.hpp"
3636
#include "opencv2/core/utils/logger.hpp"
37+
#include "opencv2/core/utils/tls.hpp"
3738

3839
#include "pyopencv_generated_include.h"
3940
#include "opencv2/core/types_c.h"
@@ -141,6 +142,51 @@ class PyEnsureGIL
141142
PyGILState_STATE _state;
142143
};
143144

145+
/**
146+
* Light weight RAII wrapper for `PyObject*` owning references.
147+
* In comparisson to C++11 `std::unique_ptr` with custom deleter, it provides
148+
* implicit conversion functions that might be useful to initialize it with
149+
* Python functions those returns owning references through the `PyObject**`
150+
* e.g. `PyErr_Fetch` or directly pass it to functions those want to borrow
151+
* reference to object (doesn't extend object lifetime) e.g. `PyObject_Str`.
152+
*/
153+
class PySafeObject
154+
{
155+
public:
156+
PySafeObject() : obj_(NULL) {}
157+
158+
explicit PySafeObject(PyObject* obj) : obj_(obj) {}
159+
160+
~PySafeObject()
161+
{
162+
Py_CLEAR(obj_);
163+
}
164+
165+
operator PyObject*()
166+
{
167+
return obj_;
168+
}
169+
170+
operator PyObject**()
171+
{
172+
return &obj_;
173+
}
174+
175+
PyObject* release()
176+
{
177+
PyObject* obj = obj_;
178+
obj_ = NULL;
179+
return obj;
180+
}
181+
182+
private:
183+
PyObject* obj_;
184+
185+
// Explicitly disable copy operations
186+
PySafeObject(const PySafeObject*); // = delete
187+
PySafeObject& operator=(const PySafeObject&); // = delete
188+
};
189+
144190
static void pyRaiseCVException(const cv::Exception &e)
145191
{
146192
PyObject_SetAttrString(opencv_error, "file", PyString_FromString(e.file.c_str()));
@@ -293,6 +339,74 @@ bool parseNumpyScalar(PyObject* obj, T& value)
293339
return false;
294340
}
295341

342+
TLSData<std::vector<std::string> > conversionErrorsTLS;
343+
344+
inline void pyPrepareArgumentConversionErrorsStorage(std::size_t size)
345+
{
346+
std::vector<std::string>& conversionErrors = conversionErrorsTLS.getRef();
347+
conversionErrors.clear();
348+
conversionErrors.reserve(size);
349+
}
350+
351+
void pyRaiseCVOverloadException(const std::string& functionName)
352+
{
353+
const std::vector<std::string>& conversionErrors = conversionErrorsTLS.getRef();
354+
const std::size_t conversionErrorsCount = conversionErrors.size();
355+
if (conversionErrorsCount > 0)
356+
{
357+
// In modern std libraries small string optimization is used = no dynamic memory allocations,
358+
// but it can be applied only for string with length < 18 symbols (in GCC)
359+
const std::string bullet = "\n - ";
360+
361+
// Estimate required buffer size - save dynamic memory allocations = faster
362+
std::size_t requiredBufferSize = bullet.size() * conversionErrorsCount;
363+
for (std::size_t i = 0; i < conversionErrorsCount; ++i)
364+
{
365+
requiredBufferSize += conversionErrors[i].size();
366+
}
367+
368+
// Only string concatenation is required so std::string is way faster than
369+
// std::ostringstream
370+
std::string errorMessage("Overload resolution failed:");
371+
errorMessage.reserve(errorMessage.size() + requiredBufferSize);
372+
for (std::size_t i = 0; i < conversionErrorsCount; ++i)
373+
{
374+
errorMessage += bullet;
375+
errorMessage += conversionErrors[i];
376+
}
377+
cv::Exception exception(CV_StsBadArg, errorMessage, functionName, "", -1);
378+
pyRaiseCVException(exception);
379+
}
380+
else
381+
{
382+
cv::Exception exception(CV_StsInternal, "Overload resolution failed, but no errors reported",
383+
functionName, "", -1);
384+
pyRaiseCVException(exception);
385+
}
386+
}
387+
388+
void pyPopulateArgumentConversionErrors()
389+
{
390+
if (PyErr_Occurred())
391+
{
392+
PySafeObject exception_type;
393+
PySafeObject exception_value;
394+
PySafeObject exception_traceback;
395+
PyErr_Fetch(exception_type, exception_value, exception_traceback);
396+
PyErr_NormalizeException(exception_type, exception_value,
397+
exception_traceback);
398+
399+
PySafeObject exception_message(PyObject_Str(exception_value));
400+
std::string message;
401+
getUnicodeString(exception_message, message);
402+
#ifdef CV_CXX11
403+
conversionErrorsTLS.getRef().push_back(std::move(message));
404+
#else
405+
conversionErrorsTLS.getRef().push_back(message);
406+
#endif
407+
}
408+
}
409+
296410
} // namespace
297411

298412
typedef std::vector<uchar> vector_uchar;

0 commit comments

Comments
 (0)