如何在Java中实现OpenCV C++的ptr<uchar>(y)及眼球检测代码?
Converting OpenCV C++
ptr<uchar> to Java and Completing the Eyeball Detection Function In your C++ code, eye.ptr<uchar>(y) gives you a direct pointer to the start of the y-th row of the grayscale eye image. Java's OpenCV bindings don't offer direct pointer access, but we can replicate this functionality efficiently using byte arrays (since uchar maps directly to Java's byte type).
Key Replacement for ptr<uchar>
Instead of a pointer, use Mat.get(int row, byte[] buffer) to load the entire row's pixel values into a byte array. This is much faster than fetching individual pixels one by one with get(row, col).
Complete Java Implementation
Here's the full converted function, with fixes for data types and performance optimizations:
import org.opencv.core.Mat; import org.opencv.core.Vec3f; import org.opencv.core.MatOfVec3f; public Vec3f getEyeball(Mat eye, MatOfVec3f circles) { Vec3f[] circlesArray = circles.toArray(); int[] sums = new int[circlesArray.length]; // Buffer to hold one full row of pixel data byte[] rowBuffer = new byte[eye.cols()]; for (int y = 0; y < eye.rows(); y++) { // Load the entire y-th row into our buffer (replaces C++'s ptr<uchar>(y)) eye.get(y, rowBuffer); for (int x = 0; x < eye.cols(); x++) { // Convert signed byte to unsigned int (matches uchar's 0-255 range) int pixelValue = rowBuffer[x] & 0xFF; for (int i = 0; i < circlesArray.length; i++) { Vec3f circle = circlesArray[i]; // Extract and round circle parameters int centerX = Math.round((float) circle.val[0]); int centerY = Math.round((float) circle.val[1]); int radius = Math.round((float) circle.val[2]); // Calculate squared distance to avoid costly sqrt operations int dx = x - centerX; int dy = y - centerY; int squaredDistance = dx * dx + dy * dy; int squaredRadius = radius * radius; if (squaredDistance < squaredRadius) { sums[i] += pixelValue; } } } } // Find the circle with the smallest sum of pixel values int smallestSum = Integer.MAX_VALUE; int smallestSumIndex = -1; for (int i = 0; i < sums.length; i++) { if (sums[i] < smallestSum) { smallestSum = sums[i]; smallestSumIndex = i; } } return circlesArray[smallestSumIndex]; }
Important Notes
- Unsigned Byte Handling: Java's
byteis signed, so we userowBuffer[x] & 0xFFto convert it to the correct 0-255 range that matches OpenCV'suchar. - Data Type Match: Your original Java code used
MatOfRect, but since the C++ code usesvector<Vec3f>(storing circle centers and radii), we switched toMatOfVec3fto maintain data consistency. - Performance Boost: Replacing
Math.powwith squared distance calculations avoids unnecessary floating-point operations, making the code faster without changing the result.
内容的提问来源于stack exchange,提问作者Blazing Forrest
相关产品推荐
相关产品推荐

