use of org.bytedeco.opencv.opencv_core.Mat in project qupath by qupath.
the class OpenCVTools method mergeChannels.
/**
* Merge channels from a multichannel {@link Mat}.
* May be more convenient than OpenCV's built-in approach.
*
* @param channels separate channels
* @param dest optional destination (may be null)
* @return merged {@link Mat}, which will be the same as dest if provided
* @throws IllegalArgumentException if the number of channels in the output would be greater than {@link opencv_core#CV_CN_MAX}
*/
@SuppressWarnings("unchecked")
public static Mat mergeChannels(Collection<? extends Mat> channels, Mat dest) throws IllegalArgumentException {
if (dest == null)
dest = new Mat();
boolean firstMat = true;
boolean allSingleChannel = true;
int rows = -1;
int cols = -1;
int depth = 0;
int nChannels = 0;
for (var m : channels) {
if (firstMat) {
rows = m.rows();
cols = m.cols();
depth = m.depth();
if (rows < 0 || cols < 0)
throw new IllegalArgumentException("Rows and columns must be >= 0");
firstMat = false;
}
int nc = m.channels();
allSingleChannel = allSingleChannel && nc == 1;
nChannels += nc;
if (depth != m.depth() || rows != m.rows() || cols != m.cols())
throw new IllegalArgumentException("mergeChannels() requires all Mats to have the same dimensions and depth!");
}
// We can only use OpenCV's merge if all Mats are single-channel
boolean mixChannels = !allSingleChannel;
if (nChannels > opencv_core.CV_CN_MAX)
throw new IllegalArgumentException("Can't merge more than " + opencv_core.CV_CN_MAX + " channels (you requested " + nChannels + ")");
try (var scope = new PointerScope()) {
if (mixChannels) {
dest.create(rows, cols, opencv_core.CV_MAKETYPE(depth, nChannels));
var vecSource = new MatVector(channels.toArray(Mat[]::new));
var vecDest = new MatVector(dest);
int[] inds = new int[nChannels * 2];
for (int i = 0; i < nChannels; i++) {
inds[i * 2] = i;
inds[i * 2 + 1] = i;
}
opencv_core.mixChannels(vecSource, vecDest, new IntPointer(inds));
} else {
opencv_core.merge(new MatVector(channels.toArray(Mat[]::new)), dest);
}
// scope.deallocate();
}
return dest;
}
use of org.bytedeco.opencv.opencv_core.Mat in project qupath by qupath.
the class OpenCVTools method extractPixels.
/**
* Extract pixels as a float[] array.
* <p>
* <p>
* In QuPath v0.2 this would return only the pixels in the first channel.
* In v0.3+ it should return all pixels.
*
* @param mat
* @param pixels
* @return
* @implNote in its current form, this is not very efficient.
*/
public static float[] extractPixels(Mat mat, float[] pixels) {
if (pixels == null)
pixels = new float[(int) totalPixels(mat)];
Mat mat2 = null;
if (mat.depth() != opencv_core.CV_32F) {
mat2 = new Mat();
mat.convertTo(mat2, opencv_core.CV_32F);
ensureContinuous(mat2, true);
} else
mat2 = ensureContinuous(mat, false);
FloatIndexer idx = mat2.createIndexer();
idx.get(0L, pixels);
idx.release();
// buffer.get(pixels);
if (mat2 != mat)
mat2.close();
return pixels;
}
use of org.bytedeco.opencv.opencv_core.Mat in project qupath by qupath.
the class OpenCVTools method fillSmallHoles.
/**
* Fill holes in a binary image (1-channel, 8-bit unsigned) with an area <= maxArea.
*
* @param matBinary
* @param maxArea
*/
public static void fillSmallHoles(Mat matBinary, double maxArea) {
Mat matHoles = new Mat();
invertBinary(matBinary, matHoles);
MatVector contours = new MatVector();
Mat hierarchy = new Mat();
opencv_imgproc.findContours(matHoles, contours, hierarchy, opencv_imgproc.RETR_CCOMP, opencv_imgproc.CHAIN_APPROX_SIMPLE);
Scalar color = Scalar.WHITE;
int ind = 0;
Point offset = new Point(0, 0);
Indexer indexerHierarchy = hierarchy.createIndexer();
for (int c = 0; c < contours.size(); c++) {
Mat contour = contours.get(c);
// TODO: Check hierarchy indexing after switch to JavaCPP!!
if (indexerHierarchy.getDouble(0, ind, 3) >= 0 || opencv_imgproc.contourArea(contour) > maxArea) {
ind++;
continue;
}
opencv_imgproc.drawContours(matBinary, contours, c, color, -1, opencv_imgproc.LINE_8, null, Integer.MAX_VALUE, offset);
ind++;
}
}
use of org.bytedeco.opencv.opencv_core.Mat in project qupath by qupath.
the class OpenCVTools method extractZStack.
/**
* Extract a list of Mats, where each Mat corresponds to a z-slice.
*
* @param server
* @param request
* @param zMin first z slice, inclusive
* @param zMax last z slice, exclusive
* @return
* @throws IOException
*/
public static List<Mat> extractZStack(ImageServer<BufferedImage> server, RegionRequest request, int zMin, int zMax) throws IOException {
List<Mat> list = new ArrayList<>();
for (int z = zMin; z < zMax; z++) {
RegionRequest request2 = RegionRequest.createInstance(server.getPath(), request.getDownsample(), request.getX(), request.getY(), request.getWidth(), request.getHeight(), z, request.getT());
BufferedImage img = server.readBufferedImage(request2);
list.add(imageToMat(img));
}
return list;
}
use of org.bytedeco.opencv.opencv_core.Mat in project qupath by qupath.
the class OpenCVTools method stdDev.
/**
* Get the standard deviation of an image, across all pixels (regardless of channels), ignoring NaNs.
* @param mat
* @return the standard deviation of all pixels in the image
*/
public static double stdDev(Mat mat) {
Mat temp;
if (mat.channels() == 1)
temp = mat;
else
temp = mat.reshape(1, mat.rows() * mat.cols());
var output = channelStdDev(temp);
assert output.length == 1;
return output[0];
}
Aggregations