Performing the same Laplacian operation in C++
and Python
appears to produce different results. Notably, the C++
variant does not report negative slopes in the result matrix.
I am using (C++):
Laplacian(img.clone(), img, CV_16S, 1, 1, 0, BORDER_DEFAULT);
and (Python):
img = cv2.Laplacian(img, ddepth=cv2.CV_16S, ksize=1, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)
By processing the C++ data into a more friendly text format:
outfile.open("cpp.csv");
outfile.close();
for (size_t i = 0; i < img.size().width; i++) {
outfile.open("cpp.csv", std::ios_base::app);
for (size_t j = 0; j < img.size().height; j++) {
outfile << (int16_t)img.at<uchar>(j, i);
if (j < img.size().height - 1) {
outfile << ",";
}
}
outfile << std::endl;
outfile.close();
}
I can then compare the values with Numpy
.
cpp = np.loadtxt("./cpp.csv", delimiter=',')
print("python lap min:", np.min(img))
print("c++ lap min:", np.min(cpp))
This output shows us that the CPP code is not recording negative values:
python lap min: -133 c++ lap min: 0.0
So what is happening here? Surely I have made some sort of error, because there must be negative values in a Laplacian transformation somewhere if the image luminosity values are not static.
Image Source
The source image for each test case is a 1920x1080 full color PNG image with distinct light and dark areas. I'm using a photo of the moon. The image is converted to CV_8UC1 prior to the Laplace transformation.
Strict Typing
I have explicitly told C++
to store data with the int16_t
type, which is implicitly signed by default, rather than just an int
. This typing matches the output from the Laplacian storage matrix (CV_16S
). Adding an explicit "signed" to "int16_t" produces the same result. My understanding is that the at
function requires uchar
typing similar to this SO answer. This is where I was wrong!!!
Version Note
Python OpenCV version: 4.1.1 (or 4.4.0, see edit section)
C++ OpenCV version: 3.4.1 (or 4.4.0, see edit section)
The documentation for these versions (3.4.1 and 4.1.1) shows no appreciable difference between the two.
Similar Questions
Laplacian variation between C++
and Python
appears common on SO, but nothing had anything useful for this. I read:
- Laplacian does not give desired output
- OpenCV - laplacian different results in Python and C++
- opencv 2.4.0 laplacian different results depending on API used?
Edit - Upgrading C++ OpenCV lib
I built OpenCV
v.4.4 from git, and compiled the C++
version of the code with pkg-config --cflags --libs opencv4
. The same error persists. (cv2.getBuildInformation()
says the Python is running 4.4 as well).
Edit2 - context from a Git issue:
I found a similar issue on the github repo (here) where the solution was storing the Laplacian result as a new Mat
. My original code uses Laplacian(img.clone(), img, ...)
which should produce a "deep copy" of the img
matrix in place, avoiding the problem reported by the OP. I tested my code with a unique matrix anyway Laplacian(outputimg, img, ...)
and saw no change in results.
Edit3 - Generalizing the problem
I processed the original code, this time replacing the Laplacian filter with either a Sobel and a custom filter2D
filter. The same result is observed, Python
produces good values while C++
does not.
Edit4 - Post-answer cleanup
Since this was a simple typing error, I have crossed out most of the extraneous information. This leaves it my original attempts readable, but it makes it obvious that they were not useful in the end.