scalacv

package scalacv

Members list

Packages

package scalacv.graphs
package scalacv.vision

Type members

Classlikes

enum AdaptiveMethod(val cvValue: Int)

How adaptive thresholding weights each pixel's neighbourhood. A true enumeration.

How adaptive thresholding weights each pixel's neighbourhood. A true enumeration.

Attributes

Source
Enums.scala
Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
enum BorderType(val cvValue: Int)

Border extrapolation.

Border extrapolation.

Plain rather than an enum-with-modifiers: BORDER_ISOLATED is a modifier, but it only means anything for ROI-based calls that scalacv does not expose yet, so it is deliberately omitted rather than offered and ignored.

==One type, two domains==

OpenCV packs two different sets of accepted values into this one int, and this enum is the union of them. copyMakeBorder (behind pad and border) and warpAffine (behind rotated) honour all five modes. The imgproc filter family — gaussianBlur, boxBlur, sobel, laplacian — does not: it rejects BorderType.Wrap, see that case and BorderType.requireFilterSupport.

Splitting the type (a FilterBorder without Wrap, widening into a TransformBorder with it) is the end state that would make the mistake unrepresentable, but it is a breaking change to four public signatures. Until then BorderType.requireFilterSupport is the check every filter operation must run on its border parameter, so the rejection lands at the Scala boundary instead of as an assertion failure inside OpenCV. BORDER_TRANSPARENT stays out of the enum entirely for a related reason: copyMakeBorder throws on it, and warpAffine with it leaves the freshly-allocated destination uninitialised, so the value can only ever produce a crash or garbage pixels.

Attributes

Companion
object
Source
Enums.scala
Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object BorderType

Attributes

Companion
enum
Source
Enums.scala
Supertypes
trait Sum
trait Mirror
class Object
trait Matchable
class Any
Self type
BorderType.type
final class BorrowedMat

A liveness-checked, read-only view over a video frame that belongs to someone else.

A liveness-checked, read-only view over a video frame that belongs to someone else.

Video.frames and scalacv.zio's frameStream decode every frame into one reused native buffer — that is what keeps a two-hour video flat in memory. Before this type existed, the iterator handed out that buffer as a raw Mat, and nothing stopped a caller from smuggling the reference out of the loop: the next read overwrote its pixels underneath the retained reference, and once the scope released the buffer the retained reference pointed at freed native memory. Reading it was not an exception, it was a SIGSEGV — the exact crash Managed exists to prevent everywhere else in the library.

BorrowedMat detects sequential use after the frame source advances or closes. Every forwarded access — including the mat escape hatch — checks a liveness flag first and rejects an already-spent view with IllegalStateException before crossing JNI. The raw Mat returned by mat is checked only at extraction; it must not be retained or released.

This is a single-consumer borrow, not a concurrent lifetime lock. The check and native access are not atomic with advancing or closing the source: do not use a view concurrently with either operation. Clone while the source is paused if another thread/fiber needs the pixels. Serialized consumers may hop threads, but a volatile flag alone cannot make overlapping access safe.

Only the read-only surface a frame consumer needs is forwarded — geometry, pixel reads, dataAddr for identity checks, and clone for "I need to keep this one". Mutation is not forwarded on purpose: the buffer is owned by the frame source and is about to be decoded over, so a put through the view would be a write into someone else's next frame.

==What "live" means==

A view is live from the moment the frame source produces it until the source is next asked for a frame (next/hasNext on Video.frames' iterator, the next pull on a zio stream) or the source closes — whichever comes first. Asking is advancing: with decode-ahead iterators hasNext already overwrites the buffer, so the previous view is spent by the call, not by the one after.

Not a value type: two views over the same buffer compare by reference identity, and dataAddr — not equals — is the way to ask "same underlying buffer?".

Attributes

Source
BorrowedMat.scala
Supertypes
class Object
trait Matchable
class Any
object Build

Reports how this artifact was built. Present from the first commit so the build has a real compilation unit and so a consumer can report an accurate version in a bug report.

Reports how this artifact was built. Present from the first commit so the build has a real compilation unit and so a consumer can report an accurate version in a bug report.

Every value here is generated from build.mill's Deps block rather than typed out a second time — see core.generatedSources. That is not tidiness: a version written down in two places is a version that eventually disagrees with itself, and the failure is silent. A dependency bump used to move the build and leave this object (and the "add these lines" help text in OpenCv and scalacv.vision.Cascades) quoting the previous release, which is precisely the number a bug report or a broken classpath depends on being right.

Attributes

Source
Build.scala
Supertypes
class Object
trait Matchable
class Any
Self type
Build.type
object Camera

Attributes

Companion
class
Source
Camera.scala
Supertypes
class Object
trait Matchable
class Any
Self type
Camera.type
final class Camera extends AutoCloseable

High-level video capture — a camera or a video file, walked as owned Images.

High-level video capture — a camera or a video file, walked as owned Images.

Camera is the high-level counterpart to Video. Where Video.frames hands you one reused, borrowed Mat for zero-copy speed, Camera hands you a fresh owned Image per frame — one you can transform, detect on, annotate, or keep, on the same terms as any other Image. The price is one frame copy per iteration; when that matters, drop to Video.frames on the borrowed capture.

import scalacv.*
OpenCv.load()

// Process every frame of a file into an edge video. Reading `.mp4` is fine — the container restriction
// is the writer's: the default codec is MJPG, which opens only in an `.avi` (see [[Codec.Mjpg]]).
Camera.usingFile("clip.mp4") { cam =>
 cam.recordTo("edges.avi")(_.gray.canny(80, 160).convert(ColorConversion.GrayToBgr))
}

// Grab a single webcam snapshot:
Camera.using(0)(_.snapshot().flatMap(_.write("shot.png")))

The capture is caller-owned: close it, or acquire it through Camera.using / Camera.usingFile, which close for you. Camera is AutoCloseable.

Attributes

Companion
object
Source
Camera.scala
Supertypes
trait AutoCloseable
class Object
trait Matchable
class Any
enum CaptureBackend(val cvValue: Int)

Which videoio backend to ask for.

Which videoio backend to ask for.

Any is the right answer almost always: OpenCV tries its registered backends in priority order and uses the first that can read the source. Naming one is for when that choice is wrong — forcing CaptureBackend.FFmpeg on a file that the image-sequence reader would otherwise claim, or forcing CaptureBackend.V4L2 on Linux so that a camera's native pixel format is honoured.

A backend that is not compiled into the OpenCV build on the classpath simply cannot open anything, so naming one turns a working open into a failing one. The bytedeco 4.13.0 builds do not all carry the same set — this is a portability decision, not a tuning knob.

Attributes

Source
Video.scala
Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final case class CaptureInfo(width: Int, height: Int, fps: Double, frameCount: Long, backendName: String)

What the backend claims about an open capture.

What the backend claims about an open capture.

Every field is a CAP_PROP_* query, and every one of them is advisory. A live camera usually reports frameCount == 0 (or -1) because the question is meaningless; some containers report a frameCount that is off by a frame or two from what actually decodes; fps can be 0 for a camera that has not delivered a frame yet. Use these to size a org.opencv.videoio.VideoWriter or to show progress — never as a loop bound. The frame count that is true is the one frames hands you.

Attributes

Source
Video.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final case class CaptureOptions(backend: CaptureBackend = ..., openTimeout: Option[FiniteDuration] = ..., readTimeout: Option[FiniteDuration] = ..., warmupFrames: Option[Int] = ...)

How a capture should be opened.

How a capture should be opened.

==Timeouts are best-effort, and off by default==

VideoCapture.read has no timeout overload and blocks in native code, so a stream that stops delivering hangs the calling thread with nothing scalacv can do about it from the JVM side. OpenCV's only lever is CAP_PROP_OPEN_TIMEOUT_MSEC / CAP_PROP_READ_TIMEOUT_MSEC, which is:

  • Backend-dependent. FFMPEG and GStreamer honour them for network sources. V4L2, AVFoundation and the built-in MJPEG reader ignore them entirely. Nothing in the API reports which you got.
  • Only settable at open time. VideoCapture.set on a not-yet-opened capture returns false (measured), so the values have to travel through the open(source, backend, params) overload.
  • Rejected outright by backends that do not understand them. Measured on this build: opening a local .avi with the timeout parameters attached yields isOpened == false, where the same file opens fine without them. Video therefore retries without the parameters rather than reporting a failure that is really "your backend has no timeout support".

They default to None because of the third point: paying a failed open, plus OpenCV's stderr noise, on every local file to configure something local files never need is the wrong default. Set them for network sources — RTSP, HTTP — where a hang is the failure mode you actually face.

==Why a camera needs warming up and a file does not==

A webcam is not ready the instant open returns. Auto-exposure, auto-white-balance and auto-gain are closed loops running on the device, and they need a handful of real frames to converge — which is why a naive open-then-snapshot so often yields a black or badly-under-exposed image and reports it as a success. There is no property to poll for "converged", so the only fix is to pull some frames and throw them away.

warmupFrames is how many to discard before the capture is handed back. It defaults to None, which means "let the source decide": Video.open(index, …) discards 5 and Video.open(source, …) discards 0. That split is the point — a file or an RTSP URL has no exposure loop, its first frame is exactly as correct as its hundredth, and discarding frames there would silently skip real content. Set it explicitly to override either default (Some(0) disables warm-up on a camera).

Value parameters

backend

which videoio backend to ask for; see CaptureBackend.

openTimeout

best-effort cap on how long opening the source may block.

readTimeout

best-effort cap on how long a single frame read may block.

warmupFrames

how many frames to grab and discard immediately after opening; None takes the per-source default described above.

Attributes

Companion
object
Source
Video.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all

Attributes

Companion
class
Source
Video.scala
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
enum Codec(val fourcc: Int)

A video container/codec, as a FOURCC — pure bit packing, no native call, so a codec can be named before OpenCv.load().

A video container/codec, as a FOURCC — pure bit packing, no native call, so a codec can be named before OpenCv.load().

Attributes

Companion
object
Source
Codec.scala
Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object Codec

Attributes

Companion
enum
Source
Codec.scala
Supertypes
trait Sum
trait Mirror
class Object
trait Matchable
class Any
Self type
Codec.type
enum ColorConversion(val cvValue: Int)

Colour space conversions. A true enumeration.

Colour space conversions. A true enumeration.

Attributes

Source
Enums.scala
Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
enum Colormap(val cvValue: Int)

A false-colour map — turns a single-channel image (a depth map, a motion field, any data) into a colour heatmap. The perceptually-uniform ones (Colormap.Viridis, Colormap.Magma, Colormap.Inferno, Colormap.Plasma, Colormap.Turbo) are the honest choice for data; Colormap.Jet is the classic-but-misleading rainbow.

A false-colour map — turns a single-channel image (a depth map, a motion field, any data) into a colour heatmap. The perceptually-uniform ones (Colormap.Viridis, Colormap.Magma, Colormap.Inferno, Colormap.Plasma, Colormap.Turbo) are the honest choice for data; Colormap.Jet is the classic-but-misleading rainbow.

Attributes

Source
Enums.scala
Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final case class Contour(points: Seq[Point])

One connected outline, copied out of native memory.

One connected outline, copied out of native memory.

OpenCV hands contours back as a java.util.List[MatOfPoint] — a list of live native handles the caller is expected to free individually. That is the single most reliable leak in the OpenCV Java API: nothing in the signature says the list owns anything, and the objects survive every reasonable-looking use of the result. So findContours copies the points across the boundary and frees the natives before it returns, and this type is ordinary immutable Scala data with no pointer behind it. It stays valid after the source Mat is released.

The measurements (Point carries Double) come back whole: findContours produces CV_32SC2, so every coordinate is an integer that happens to be widened.

Construction copies the points into an immutable Vector (see the companion's apply): the metrics are lazy, so a Contour that merely retained the caller's Seq would see a mutable buffer's later edits halfway through a measurement chain, and convexHull indexes into the points once per hull vertex — constant-time against a Vector, quadratic against a List.

Attributes

Companion
object
Source
Contours.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object Contour

Attributes

Companion
class
Source
Contours.scala
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
Contour.type
enum ContourApproximation(val cvValue: Int)

How findContours compresses each contour. A true enumeration.

How findContours compresses each contour. A true enumeration.

Attributes

Source
Enums.scala
Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
enum ContourRetrieval(val cvValue: Int)

Which contours findContours reports. A true enumeration.

Which contours findContours reports. A true enumeration.

Attributes

Source
Enums.scala
Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object Cv

The error policy.

The error policy.

The core cannot be "total". org.opencv.core.CvException escapes from ordinary in-memory operations, including on the empty Mat that a failed imread hands back, and no wrapper can prevent that. So scalacv draws the line deliberately:

  • Either[CvError, A] where failure is data-dependent and expected — a file that is not there, bytes that do not decode, a model that will not load.
  • Thrown IllegalArgumentException for precondition violations, which are programmer errors and should not be pattern-matched.
  • Propagated CvError.NativeCall for everything OpenCV throws at us that we did not anticipate. Wrapped so the operation is named, never swallowed.

Attributes

Source
Cv.scala
Supertypes
class Object
trait Matchable
class Any
Self type
Cv.type
object CvError

Attributes

Companion
class
Source
CvError.scala
Supertypes
trait Sum
trait Mirror
class Object
trait Matchable
class Any
Self type
CvError.type
sealed abstract class CvError(message: String, cause: Throwable | Null) extends RuntimeException

Everything scalacv can fail with.

Everything scalacv can fail with.

Modelled as an exception hierarchy rather than a pure ADT because it has to interoperate with a JNI boundary that throws: org.opencv.core.CvException escapes from ordinary Imgproc calls, and no wrapper can make the core total. The API returns Either[CvError, A] where failure is data-dependent and expected — a missing file, an undecodable image — and throws for programmer errors.

Attributes

Companion
object
Source
CvError.scala
Supertypes
class RuntimeException
class Exception
class Throwable
trait Serializable
class Object
trait Matchable
class Any
Show all
Known subtypes
class DecodeFailed
class EncodeFailed
class EndOfStream
class LoadFailed
class NativeCall
Show all
object Draw

Text measurement — the one part of drawing that answers a question instead of changing an image.

Text measurement — the one part of drawing that answers a question instead of changing an image.

Attributes

Source
Draw.scala
Supertypes
class Object
trait Matchable
class Any
Self type
Draw.type
final class Filter(val name: String, run: Image => Image)

A named, composable photo filter — an Image => Image transform you can name, chain, and apply.

A named, composable photo filter — an Image => Image transform you can name, chain, and apply.

The catalog in the companion is a set of ready-made "looks" built from the Image tone, colour, and stylisation operations; each is a Filter you apply with image.filter(Filter.vintage) or compose with andThen. Because a filter is just a named transform, your own are first-class: Filter("mine")(_.gamma(1.2).saturate(1.3)).

Like every Image transform, applying a filter consumes the image and returns a new one.

Attributes

Companion
object
Source
Filter.scala
Supertypes
class Object
trait Matchable
class Any
object Filter

Attributes

Companion
class
Source
Filter.scala
Supertypes
class Object
trait Matchable
class Any
Self type
Filter.type
enum Flip(val cvValue: Int)

How to mirror an image. Named by the visible effect, not OpenCV's axis-centric flip code.

How to mirror an image. Named by the visible effect, not OpenCV's axis-centric flip code.

Attributes

Source
Enums.scala
Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
enum Font(val cvValue: Int)

Hershey fonts for putText. A true enumeration.

Hershey fonts for putText. A true enumeration.

Attributes

Source
Enums.scala
Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final class Image extends AutoCloseable

The high-level, fluent face of scalacv — an owned image you transform by chaining.

The high-level, fluent face of scalacv — an owned image you transform by chaining.

Image is the layer to reach for first. It wraps a single native Mat and lets you express the common OpenCV shape — read, transform, detect, annotate, write — as one readable chain:

import scalacv.*
OpenCv.load()

for _ <- Image.read("photo.jpg").flatMap(_.gray.blur(2).canny(80, 160).write("edges.png"))
yield ()

==Move semantics: a transform consumes the image==

Every transform (gray, blur, canny, resize, crop, a draw*) returns a new Image and spends the one it was called on — using the old handle afterwards throws IllegalStateException rather than reading freed memory. That is what makes the chain leak-free without a scope: each step frees (or hands on) the previous Mat, so a long pipeline holds exactly one live Mat at a time, never a pile of intermediates. It is Mats.chain's guarantee, surfaced as a type.

The trade is that you cannot use one Image twice. To branch, take a copy first, or drop to the mid-level API on a borrowed mat.

==Queries borrow, terminals consume==

A query (width, faces, qrCodes, contours) only reads, so it leaves the image alive. A terminal (write, bytes, close) consumes it and releases the Mat. If a value escapes the chain without ever reaching a terminal it leaks, exactly as a stray Managed would — so prefer Image.reading, which owns live successors and copy branches until its callback returns. managed preserves that scope; only an explicit detach transfers a branch out of it.

==Not a wall==

Image never hides the library underneath it. mat borrows the raw org.opencv.core.Mat for any org.opencv.* call this type does not wrap; managed hands the whole Managed over. The high-level API is the pleasant default, not a ceiling. Domain verbs that only happen to start from an image — face and marker detection, pose and track overlays, OCR preparation, background replacement — are extension methods brought in with import scalacv.vision.*, not members of this class, which is why they are absent below; they read image.faces(detector) all the same.

==Failures==

A transform does not return an Either: when OpenCV itself rejects the pixels (a data-dependent failure this library cannot foresee), the op throws CvError.NativeCall, naming the operation — an unchecked throw, so it is invisible at the call site. Argument mistakes this library can see are rejected up front with IllegalArgumentException. Only the Either-returning boundary methods (Image.read, write, bytes, Image.decode) turn failure into a value. To fold a transform's throw into an Either too, wrap it with Cv.attempt. Reusing an already-consumed image throws IllegalStateException; see Managed for -Dscalacv.trackOwnership=true, which points the error at the consuming call.

Image is AutoCloseable, so scala.util.Using manages it too.

Attributes

Companion
object
Source
Image.scala
Supertypes
trait AutoCloseable
class Object
trait Matchable
class Any
object Image

Attributes

Companion
class
Source
Image.scala
Supertypes
class Object
trait Matchable
class Any
Self type
Image.type
object Images

Reading, writing, encoding and decoding images — the boundary between OpenCV and everything else.

Reading, writing, encoding and decoding images — the boundary between OpenCV and everything else.

This is the one place in the library where OpenCV's error reporting is genuinely inconsistent, and the whole point of the object is to flatten that into a single Either. Two distinct failure shapes come out of org.opencv.imgcodecs.Imgcodecs:

  1. imdecode never throws for bytes that are not an image. It returns a Mat with empty() == true (and logs a findDecoder warning to stderr). Anyone who forgets the empty() check gets a CvException several call frames later, from an Imgproc operation that had nothing to do with the mistake.
  2. imencode throws CvException when the extension names no known encoder — so haveImageWriter is consulted first and that case is returned as CvError.EncodeFailed before the throw can happen, rather than being recovered from OpenCV's error text.

Every function here returns Either[CvError, ?] covering both. The encode failures share the one CvError.EncodeFailed type, so case EncodeFailed(...) catches them all.

==The file I/O is done by the JVM, not by OpenCV== read and write do not call imread/imwrite. They open the file with java.nio.file and leave OpenCV only the codec work, through decode and encode. The reason is the path. The JNI layer narrows a Java String with GetStringUTFChars, so the native side receives modified UTF-8 bytes, and OpenCV's imgcodecs hands those bytes straight to fopen. On Windows the C runtime interprets them in the process's ANSI code page, so any non-ASCII character in the path resolves to a different, nonexistent name: imread then returns an empty Mat and imwrite returns false — indistinguishable from "the file is not there" and "the directory is not writable". Upstream has not fixed this (opencv#4292 is still open in 4.13) and exposes no wide-character entry point to call instead. Reading and writing the bytes on the JVM side avoids the narrowing altogether, and as a side effect lets both functions report which of the causes they used to lump together actually happened.

The price is that the encoded file passes through a JVM byte array: peak heap grows by its size, and a file above 2 GB is out of reach, because Files.readAllBytes cannot return an array that long. Routing around that with a memory-mapped buffer was rejected — imdecode needs a MatOfByte built from a JVM array anyway, so the copy is not avoidable here.

The same narrowing hazard applies to every other String-path native call in the library — VideoCapture, VideoWriter, CascadeClassifier.load, Dnn.readNet — and none of those has an in-memory equivalent to reroute through, so they remain ASCII-path-only on Windows.

==Ownership== A returned Managed[Mat] is caller-owned: nothing else holds a reference and nothing else will free it. Prefer Images.read(p).map(_.use(...)) over holding one. Mats created internally — the MatOfByte staging buffers, and the empty Mat a failed read hands back — are released here.

Attributes

Source
Images.scala
Supertypes
class Object
trait Matchable
class Any
Self type
Images.type

How imread/imdecode should decode a pixel's colour.

How imread/imdecode should decode a pixel's colour.

Attributes

Source
Enums.scala
Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object ImreadFlags

Attributes

Companion
class
Source
Enums.scala
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
final case class ImreadFlags(color: ImreadColor, scale: ImreadScale = ..., ignoreOrientation: Boolean = ...)

Image reading flags — a total model, not a bitmask.

Image reading flags — a total model, not a bitmask.

OpenCV's IMREAD_* constants look like OR-able bits but are not: each IMREAD_REDUCED_* value already bakes in its colour bit, and IMREAD_UNCHANGED is -1, whose bits swamp everything else. OR-ing a colour with a reduced-size flag therefore silently decodes the wrong image. So the (colour, scale) pair maps totally onto exactly one named constant instead of composing, and only ignoreOrientation (bit 128) is a genuinely independent flag that may be OR-ed on top.

Reduced-size decode exists only for ImreadColor.Grayscale and ImreadColor.Color, and ImreadColor.Unchanged (-1) can carry no extra bit at all; the two requires reject the combinations OpenCV has no constant for, rather than quietly OR-ing them into something else.

Attributes

Companion
object
Source
Enums.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
enum ImreadScale(val denom: Int)

The fraction of full resolution to decode at. OpenCV's reduced-size decode is cheaper than a full read followed by a resize, because the codec skips the discarded detail rather than producing it first.

The fraction of full resolution to decode at. OpenCV's reduced-size decode is cheaper than a full read followed by a resize, because the codec skips the discarded detail rather than producing it first.

Attributes

Source
Enums.scala
Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
enum Interpolation(val cvValue: Int)

Interpolation for resize and warps. A true enumeration.

Interpolation for resize and warps. A true enumeration.

Attributes

Source
Enums.scala
Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final case class Intrinsics(fx: Double, fy: Double, cx: Double, cy: Double, distortion: Seq[Double] = ...)

A pinhole camera's intrinsics — what turns a pixel measurement into a metric one.

A pinhole camera's intrinsics — what turns a pixel measurement into a metric one.

fx/fy are the focal length in pixels, cx/cy the principal point (usually near the image centre). All calibration values must be finite; focal lengths must be positive. distortion is OpenCV's radial/tangential coefficients (k1, k2, p1, p2[, k3 …]); leave it empty for an ideal lens. Only the counts OpenCV itself accepts are allowed — see Intrinsics.ValidDistortionSizes. A real camera's numbers come from a chessboard calibration; when you have not calibrated, Intrinsics.approx gives a serviceable guess from the image size and a field-of-view estimate — good enough to see an augmented overlay track, not good enough to measure with.

This is the core camera model the vision layer builds on: scalacv.vision.Ar, HeadPose and Localizer all take an Intrinsics, scalacv.vision.Calibration produces one, and Image.undistort consumes one.

Attributes

Companion
object
Source
Intrinsics.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object Intrinsics

Attributes

Companion
class
Source
Intrinsics.scala
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
Intrinsics.type
enum LineType(val cvValue: Int)

Line rasterisation. A true enumeration.

Line rasterisation. A true enumeration.

Attributes

Source
Enums.scala
Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object Managed

Attributes

Companion
class
Source
Managed.scala
Supertypes
class Object
trait Matchable
class Any
Self type
Managed.type
final class Managed[A] extends AutoCloseable

A native OpenCV object with a release that happens exactly once.

A native OpenCV object with a release that happens exactly once.

Two guarantees, both of which exist because getting them wrong is a JVM crash rather than an exception. Calling a method on a freed OpenCV object segfaults from native code — no stack trace, no catch, no test report; a double delete is undefined behaviour that merely often happens to survive. Measured, both.

  1. Release is a compare-and-set, so a second release is a no-op rather than a double free.
  2. Access after release throws IllegalStateException on the Scala side, before anything crosses JNI.

Prefer use over holding one of these. The scoped form is the only one where the compiler helps you.

==Diagnosing use-after-move==

The move semantics of Image mean the commonest mistake is reusing a handle a transform already consumed, and the resulting IllegalStateException fires at the reuse, which is rarely the interesting line. Start the JVM with -Dscalacv.trackOwnership=true and the exception carries, as its cause, the stack of the transform or terminal that actually spent the handle. It is off by default because it allocates a Throwable every time a handle is spent; the check that reads it lives only on the already-failing path, so a program that never misuses a handle pays nothing.

Attributes

Companion
object
Source
Managed.scala
Supertypes
trait AutoCloseable
class Object
trait Matchable
class Any
object Mats

Helpers that do not belong on a Mat: the single place a destination Mat is allocated (Mats.produce), the shared greyscale reduction, small lifts between native memory and plain Scala data, and the named preconditions the ops enforce before crossing into native code.

Helpers that do not belong on a Mat: the single place a destination Mat is allocated (Mats.produce), the shared greyscale reduction, small lifts between native memory and plain Scala data, and the named preconditions the ops enforce before crossing into native code.

Attributes

Source
Mats.scala
Supertypes
class Object
trait Matchable
class Any
Self type
Mats.type
object ModelSpec

Attributes

Companion
class
Source
Models.scala
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
ModelSpec.type
final case class ModelSpec

A downloadable model file: its fixed name, the mirror URLs to try in order, the SHA-256 the fetched bytes must match, and optionally the exact size they must have.

A downloadable model file: its fixed name, the mirror URLs to try in order, the SHA-256 the fetched bytes must match, and optionally the exact size they must have.

Integrity checking is the default: build a spec with ModelSpec.apply and its pinned hash is verified on every download and on every cache hit. Skipping the check is a deliberate, named opt-out — ModelSpec.unverified — that loses the tamper/corruption guard, so reach for it only for a model with no published checksum.

sizeBytes is not redundant with the hash; it changes the message, and only ever in the direction of being more useful. The failure it catches is the common one: a mirror that answers a model request with an HTML error page, or a Git LFS host that serves a 131-byte pointer file, both with HTTP 200. Those hash wrong, of course — but "SHA-256 mismatch" invites the reader to suspect tampering, whereas "expected 232589 bytes, got 131" says what actually happened. It is also checked first, so it costs one stat rather than a full digest of a file that was never the model.

Attributes

Companion
object
Source
Models.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object Models

A small registry and downloader for the model files scalacv's detectors need. It is the downloader: scalacv.vision.FaceDetect.downloadModel is a one-line alias for fetch(FaceDetect.modelSpec, into).

A small registry and downloader for the model files scalacv's detectors need. It is the downloader: scalacv.vision.FaceDetect.downloadModel is a one-line alias for fetch(FaceDetect.modelSpec, into).

fetch downloads to a temp file beside the target and moves it into place only after it verifies, so an interrupted run never leaves a truncated model for the next load to trip over. It is idempotent: a target that already exists (and, if a hash or size is pinned, still matches) is returned without touching the network. URLs may be http(s):// or file://, so a model you already have on disk is just another source.

The detector model specs live next to their detectors (scalacv.vision.FaceDetect.modelSpec and scalacv.vision.FaceRecognizer.modelSpec); supply your own ModelSpec for anything else.

Attributes

Source
Models.scala
Supertypes
class Object
trait Matchable
class Any
Self type
Models.type
enum MorphOp(val cvValue: Int)

Compound morphological operations (morphologyEx). Erosion and dilation have their own methods.

Compound morphological operations (morphologyEx). Erosion and dilation have their own methods.

Attributes

Source
Enums.scala
Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
enum MorphShape(val cvValue: Int)

The structuring-element shape for morphology. A true enumeration.

The structuring-element shape for morphology. A true enumeration.

Attributes

Source
Enums.scala
Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object OpenCv

Loads the OpenCV native libraries, without ever requiring a GUI toolkit.

Loads the OpenCV native libraries, without ever requiring a GUI toolkit.

The obvious approach — Loader.load(classOf[opencv_java]) — does not work on a headless machine. javacpp eagerly initialises the whole preset graph, and opencv_highgui is GTK2-linked on Linux, so on a box without GTK it throws and takes objdetect, calib3d, features2d and video down with it. objdetect is precisely what this library needs most.

libopencv_java itself links no GUI toolkit. So we bring javacpp up through a GUI-free preset, extract the platform payload, and then load the JNI shim, resolving its dependencies on demand — see satisfy for why loading them speculatively is not merely wasteful but unsafe. The result needs no apt-get install libgtk2.0-0t64 on any runner.

Attributes

Source
OpenCv.scala
Supertypes
class Object
trait Matchable
class Any
Self type
OpenCv.type
enum OutputDepth(val cvValue: Int)

The destination depth for the operators that can change it — the derivative operators, and normalize.

The destination depth for the operators that can change it — the derivative operators, and normalize.

Worth a type of its own rather than a bare int because OutputDepth.SameAsSource is a trap on the commonest input: Sobel on an 8-bit unsigned image with ddepth = -1 clips every negative derivative to zero, so half of each edge silently disappears. OutputDepth.Signed16 then convertScaleAbs is the standard fix.

Attributes

Source
Ops.scala
Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final case class PencilSketchPair(colour: Managed[Mat], grey: Managed[Mat])

The two outputs of Mat.pencilSketchBoth: the colour sketch (3-channel) and the grey one (single-channel). A named pair rather than a tuple for the same reason Thresholded is one — the field names, not positions, say which plate is which. Both Mats are owned by the receiver of the pair and must be released independently.

The two outputs of Mat.pencilSketchBoth: the colour sketch (3-channel) and the grey one (single-channel). A named pair rather than a tuple for the same reason Thresholded is one — the field names, not positions, say which plate is which. Both Mats are owned by the receiver of the pair and must be released independently.

Attributes

Source
Effects.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
enum PnpSolver(val cvValue: Int)

Which method OpenCV's solvePnP should use — the typed replacement for its SOLVEPNP_* int flags.

Which method OpenCV's solvePnP should use — the typed replacement for its SOLVEPNP_* int flags.

The choice is not cosmetic: each solver has its own degenerate-input behaviour (some answer ok = false, some abort with a native CV_Assert — see Pnp.solve), so the flag is part of a call site's error story and deserves a name, not a number. This is a subset of OpenCV's solvers, not its full catalog. See https://docs.opencv.org/4.x/d5/d1f/calib3d_solvePnP.html for each solver's point-count and geometry requirements; in particular, DLS and UPnP are fallback aliases in OpenCV, not distinct robust estimators.

Attributes

Source
Pnp.scala
Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object Point

Attributes

Companion
class
Source
Geometry.scala
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
Point.type
final case class Point(x: Double, y: Double)

A 2D point in pixel coordinates, origin top-left, x right and y down — the sub-pixel form OpenCV uses for feature and contour work, so both fields are Double.

A 2D point in pixel coordinates, origin top-left, x right and y down — the sub-pixel form OpenCV uses for feature and contour work, so both fields are Double.

Attributes

Companion
object
Source
Geometry.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object Point3

Attributes

Companion
class
Source
Geometry.scala
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
Point3.type
final case class Point3(x: Double, y: Double, z: Double)

A point in 3D space — a model coordinate for scalacv.vision.Ar pose work, in the same units you give a marker's side length (metres is the usual choice). z points out of the marker plane toward the camera.

A point in 3D space — a model coordinate for scalacv.vision.Ar pose work, in the same units you give a marker's side length (metres is the usual choice). z points out of the marker plane toward the camera.

Attributes

Companion
object
Source
Geometry.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final case class PolarLine(rho: Double, theta: Double)

A line in Hesse normal form, as HoughLines reports it: infinite, with no endpoints.

A line in Hesse normal form, as HoughLines reports it: infinite, with no endpoints.

The underlying Mat is CV_32FC2, but the fields are widened to Double at the decode boundary: every other measurement the library surfaces (Point, Contour) is a Double, and the float channels carry no precision past 24 bits for the widening to lose.

Value parameters

rho

distance in pixels from the image origin (top-left) to the line, along the normal.

theta

angle of that normal in radians. 0 is a vertical line, Pi/2 a horizontal one — the angle describes the normal, not the line, which is the usual source of confusion.

Attributes

Source
Hough.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final case class PolarLineWithVotes(rho: Double, theta: Double, votes: Int)

A PolarLine plus its accumulator score.

A PolarLine plus its accumulator score.

HoughLinesWithAccumulator exists precisely so the votes are visible; they are the only way to rank results, since the plain transform already returns them sorted but discards the magnitudes. Votes are whole numbers stored in a float channel, hence the narrowing to Int; rho and theta are widened to Double like PolarLine.

Attributes

Source
Hough.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final class Recorder extends AutoCloseable

Writes Images to a video file — the counterpart to Camera for output.

Writes Images to a video file — the counterpart to Camera for output.

A recorder is fixed at open time to one frame size, fps and codec; every frame written must match that size and be 8-bit. VideoWriter is one of the three OpenCV types with a real public release(), and the recorder is caller-owned — close it, or use Recorder.using.

Attributes

Companion
object
Source
Recorder.scala
Supertypes
trait AutoCloseable
class Object
trait Matchable
class Any
object Recorder

Attributes

Companion
class
Source
Recorder.scala
Supertypes
class Object
trait Matchable
class Any
Self type
Recorder.type
final case class Rect(x: Int, y: Int, width: Int, height: Int)

An axis-aligned integer rectangle: top-left corner (x, y) and non-negative width/height. The origin may be negative (a region of interest can extend past the top-left of the image); the extent may not.

An axis-aligned integer rectangle: top-left corner (x, y) and non-negative width/height. The origin may be negative (a region of interest can extend past the top-left of the image); the extent may not.

Attributes

Companion
object
Source
Geometry.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object Rect

Attributes

Companion
class
Source
Geometry.scala
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
Rect.type
trait Releasable[-A]

How a native OpenCV object gets freed.

How a native OpenCV object gets freed.

There are two regimes, and which one applies is not a style choice — it is dictated by what the generated Java binding exposes. Of the 188 org.opencv.* types that hold a native pointer, exactly three have a public release(): Mat, org.opencv.videoio.VideoCapture and org.opencv.videoio.VideoWriter. The other 185 — including every detector this library wraps — expose only a private static native void delete(long) plus a finalize().

Relying on that finalize() is not viable. It is not disabled (a common myth), but it only runs when the collector runs, and the collector sees ~40 bytes of Java header per multi- megabyte native buffer. Measured: 2000 unreleased 1000x1000 Mats reach 5.8 GB RSS against 144 MB when released.

Attributes

Companion
object
Source
Releasable.scala
Supertypes
class Object
trait Matchable
class Any
object Releasable

Attributes

Companion
trait
Source
Releasable.scala
Supertypes
class Object
trait Matchable
class Any
Self type
Releasable.type
final case class RigidTransform(rotation: Seq[Seq[Double]], translation: Seq[Double])

An immutable rigid mapping between two 3D coordinate frames.

An immutable rigid mapping between two 3D coordinate frames.

Rotation is row-major and points are column vectors: x_destination = R * x_source + t. Coordinates and translation use the same caller-chosen units. There are no native resources to release. The rotation must be finite, 3×3, orthonormal and have determinant +1 (absolute tolerance 1e-8); translation must contain three finite values. Invalid construction, including copy, throws IllegalArgumentException. Inputs are immutable Scala sequences, not native matrix handles.

Attributes

Companion
object
Source
RigidTransform.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all

Attributes

Companion
class
Source
RigidTransform.scala
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
enum Rotation(val cvValue: Int)

Lossless quarter-turn rotations — no interpolation, exact pixels. A true enumeration.

Lossless quarter-turn rotations — no interpolation, exact pixels. A true enumeration.

Attributes

Source
Enums.scala
Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final case class Scalar(v0: Double, v1: Double = ..., v2: Double = ..., v3: Double = ...)

A pixel value: up to four channel components, in whatever channel order the Mat uses. OpenCV's default is BGR, not RGB, so Scalar.Red is Scalar(0, 0, 255). Unset channels default to 0.

A pixel value: up to four channel components, in whatever channel order the Mat uses. OpenCV's default is BGR, not RGB, so Scalar.Red is Scalar(0, 0, 255). Unset channels default to 0.

Attributes

Companion
object
Source
Geometry.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object Scalar

Attributes

Companion
class
Source
Geometry.scala
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
Scalar.type
final case class Segment(x1: Int, y1: Int, x2: Int, y2: Int)

A line segment with real endpoints, as HoughLinesP reports it.

A line segment with real endpoints, as HoughLinesP reports it.

Integer, because the underlying Mat is CV_32SC4. Rounding here would invent precision OpenCV never produced.

Attributes

Source
Hough.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final case class Size(width: Double, height: Double)

A finite, non-negative width/height extent in pixels. Fractional extents are retained for geometry and text measurement; integer raster operations document their own rounding rule. Zero is an empty extent.

A finite, non-negative width/height extent in pixels. Fractional extents are retained for geometry and text measurement; integer raster operations document their own rounding rule. Zero is an empty extent.

Attributes

Companion
object
Source
Geometry.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object Size

Attributes

Companion
class
Source
Geometry.scala
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
Size.type
final case class TextMetrics(size: Size, baseline: Int)

What a string will occupy once drawn, from Imgproc.getTextSize.

What a string will occupy once drawn, from Imgproc.getTextSize.

Value parameters

baseline

how far the descenders reach below the baseline, in pixels. It is returned separately because drawText's anchor is the baseline's left end, not the top-left corner: a background box has to be size.height + baseline tall to enclose the text, and forgetting it clips every g and y.

size

the bounding box of the glyphs.

Attributes

Source
Draw.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
sealed trait Thickness

How wide a stroke is, or that a shape is filled instead.

How wide a stroke is, or that a shape is filled instead.

OpenCV encodes "filled" as a thickness of -1, a sentinel that ordinary arithmetic on a thickness will happily produce by accident. Worse, it is only meaningful for closed shapes: cv::line asserts 0 < thickness, so passing the sentinel to a line or to text aborts in native code. Splitting the two cases into distinct types lets the shapes that can be filled accept Thickness while lines and text accept Thickness.Stroke only — the mistake stops compiling rather than crashing.

Attributes

Companion
object
Source
Draw.scala
Supertypes
class Object
trait Matchable
class Any
Known subtypes
object Filled
class Stroke
object Thickness

Attributes

Companion
trait
Source
Draw.scala
Supertypes
trait Sum
trait Mirror
class Object
trait Matchable
class Any
Self type
Thickness.type
final case class Threshold(mode: Mode, auto: Option[Auto] = ...)

Thresholding — a bitmask, not an enumeration.

Thresholding — a bitmask, not an enumeration.

Imgproc.threshold takes a mode OR-ed with at most one automatic-threshold modifier. Modelled as enum the useful combinations would be unrepresentable, and THRESH_MASK would leak into a public API where it means nothing.

Attributes

Companion
object
Source
Enums.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object Threshold

Attributes

Companion
class
Source
Enums.scala
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
Threshold.type
final case class ThresholdResult(value: Double)

What threshold actually returns.

What threshold actually returns.

Imgproc.threshold returns a double that most wrappers discard. For Otsu and Triangle it is the threshold OpenCV chose — frequently the reason you called it at all.

Attributes

Source
Enums.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
final case class Thresholded(image: Managed[Mat], computed: ThresholdResult)

The pair Mat.threshold returns: the thresholded image plus the value OpenCV computed.

The pair Mat.threshold returns: the thresholded image plus the value OpenCV computed.

Why a pair exists at all: for Threshold.Auto.Otsu and Threshold.Auto.Triangle the whole point of the call is the threshold OpenCV chose, so dropping the double the native function returns would throw away the answer. And why a named case class rather than the (Managed[Mat], ThresholdResult) tuple this used to be: a tuple made threshold the one op that did not return a bare Managed[Mat], which broke Managed.pipe and left every call site spelling ._1. A named pair destructures the same (val Thresholded(out, result) = ...) but reads as .image / .computed everywhere else.

Attributes

Source
Enums.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object Video

Video capture: opening a source, and walking its frames without leaking one per iteration.

Video capture: opening a source, and walking its frames without leaking one per iteration.

==Why there is no frame LazyList==

The obvious shape for "the frames of a video" is a lazy sequence, and it is wrong here. LazyList memoises: once evaluated, a cell holds its head forever so that a second traversal is cheap. Applied to frames, that means every Mat the list has ever produced stays reachable — so either nothing is ever released (an unbounded native leak; a 1080p BGR frame is ~6 MB, so a minute at 30 fps is over 10 GB) or frames are released as they are consumed and the list is a field of dangling handles that the next traversal hands back as empty Mats. There is no version of the API where memoisation and per-frame release are both correct. Same argument, verbatim, for Stream, and for any Iterator combinator that retains what it has seen.

So the frame source here is an Iterator that owns exactly one Mat and decodes into it in place. It is created inside a scope, it is released when that scope ends, and it holds one frame's worth of native memory no matter how long the video is.

==The borrowing contract, enforced==

This is the one place in scalacv where a frame you are handed is not yours, and it is the exact opposite of the contract in Ops.scala. Each element is a BorrowedMat — a liveness-checked view over the iterator's single decode buffer, spent the moment the iterator advances or the frames block returns. Every access, including the BorrowedMat.mat escape hatch, throws IllegalStateException once the view is spent, so sequential retention of the view fails loudly. The raw Mat returned by .mat is checked only at extraction and remains unsafe to retain. Access must not overlap a pull or close on another thread/fiber: the liveness check is not a lock. Clone inside the loop before handing pixels to concurrent work.

  • Do read the view, record it through frame.mat, and run the Ops extensions over frame.mat: those allocate their own destination and never alias the receiver, so frame.mat.cvtColor(...) inside the loop is correct and yields a Mat you own.
  • Need to keep a frame? frame.clone() inside the loop — the clone is caller-owned — or framesCopied, which does that per frame and hands you a Managed.
  • it.toList still compiles, but every element in the list is spent by the time you look at it: N spent views, not N frames.
Video.open("clip.mp4").map { capture =>
 capture.use { c =>
   Video.frames(c) { frames =>
     frames.map(f => f.mat.cvtColor(ColorConversion.BgrToGray).use(_.findContours().size)).sum
   }
 }
}

==Exception mode==

VideoCapture.setExceptionMode(true) turns a silent false into a CvException carrying OpenCV's own message, and open uses it: a missing file becomes CvError.NativeCall quoting the path instead of a bare "it did not open". frames deliberately turns it off for the duration of the loop, because OpenCV reports end-of-file through the identical exception it uses for a broken stream — cap.cpp:533 error: (-2:Unspecified error) in function 'grab', measured on a clean five-frame file. With exception mode on there is no way to tell "the video ended" from "the camera was unplugged", so the loop would have to treat every real failure as a normal end. Off, read returning false ends the stream and a genuine decode error still surfaces as CvError.NativeCall.

Attributes

Source
Video.scala
Supertypes
class Object
trait Matchable
class Any
Self type
Video.type

Extensions

Extensions

extension (mat: Mat)
def houghLines(threshold: Int, rho: Double = ..., theta: Double = ..., srn: Double = ..., stn: Double = ..., minTheta: Double = ..., maxTheta: Double = ...): Seq[PolarLine]

The standard Hough transform: every line is infinite and expressed in polar form.

The standard Hough transform: every line is infinite and expressed in polar form.

Value parameters

maxTheta

upper bound on the reported angle, in radians.

minTheta

lower bound on the reported angle, in radians.

rho

accumulator distance resolution, in pixels.

srn

divisor for a coarse-to-fine rho; 0 (with stn) selects the classic transform.

stn

divisor for a coarse-to-fine theta.

theta

accumulator angle resolution, in radians.

threshold

minimum accumulator votes for a line to be reported.

Attributes

Throws
IllegalArgumentException

if the receiver is not a non-empty 8-bit single-channel image.

Source
Hough.scala
def houghLinesP(threshold: Int, rho: Double = ..., theta: Double = ..., minLineLength: Double = ..., maxLineGap: Double = ...): Seq[Segment]

The probabilistic Hough transform: finite segments with endpoints in image coordinates.

The probabilistic Hough transform: finite segments with endpoints in image coordinates.

Value parameters

maxLineGap

largest gap, in pixels, that will still be bridged into one segment.

minLineLength

segments shorter than this are discarded. 0 keeps everything.

rho

accumulator distance resolution, in pixels.

theta

accumulator angle resolution, in radians.

threshold

minimum accumulator votes for a line to be reported.

Attributes

Throws
IllegalArgumentException

if the receiver is not a non-empty 8-bit single-channel image.

Source
Hough.scala
def houghLinesWithAccumulator(threshold: Int, rho: Double = ..., theta: Double = ..., srn: Double = ..., stn: Double = ..., minTheta: Double = ..., maxTheta: Double = ...): Seq[PolarLineWithVotes]

As houghLines, but keeps each line's accumulator score.

As houghLines, but keeps each line's accumulator score.

Attributes

Throws
IllegalArgumentException

if the receiver is not a non-empty 8-bit single-channel image.

Source
Hough.scala
extension (mat: Mat)
def drawArrow(from: Point, to: Point, color: Scalar = ..., thickness: Stroke = ..., lineType: LineType = ..., tipLength: Double = ...): Unit

Draws a line with an arrowhead at to. Mutates the receiver.

Draws a line with an arrowhead at to. Mutates the receiver.

Value parameters

tipLength

the arrowhead's length as a fraction of the whole line, so the head stays in proportion however long the line is. OpenCV's own default is 0.1.

Attributes

Source
Draw.scala
def drawCircle(center: Point, radius: Int, color: Scalar = ..., thickness: Thickness = ..., lineType: LineType = ...): Unit

Draws a circle of radius pixels about center. Mutates the receiver.

Draws a circle of radius pixels about center. Mutates the receiver.

Attributes

Source
Draw.scala
def drawContours(contours: Seq[Contour], color: Scalar = ..., thickness: Thickness = ..., lineType: LineType = ...): Unit

Draws every contour in contours. Mutates the receiver.

Draws every contour in contours. Mutates the receiver.

This is the renderer for what findContours returns. Thickness.Filled fills them, which is the usual way to turn a set of contours back into a mask.

Attributes

Source
Draw.scala
def drawLine(from: Point, to: Point, color: Scalar = ..., thickness: Stroke = ..., lineType: LineType = ...): Unit

Draws a straight line from from to to. Mutates the receiver.

Draws a straight line from from to to. Mutates the receiver.

Coordinates outside the image are clipped, not rejected — that is OpenCV's behaviour and it is what makes drawing a detection that runs off the edge of a frame safe.

Attributes

Source
Draw.scala
def drawPolyline(points: Seq[Point], closed: Boolean = ..., color: Scalar = ..., thickness: Stroke = ..., lineType: LineType = ...): Unit

Draws a connected run of line segments through points. Mutates the receiver.

Draws a connected run of line segments through points. Mutates the receiver.

Value parameters

closed

whether to draw the closing edge from the last point back to the first. Defaults to true, matching what Contour and polygon data mean. An empty points draws nothing rather than failing: a polyline is frequently the result of a filter, and filtering everything out is a legitimate outcome, not a programming error.

Attributes

Source
Draw.scala
def drawRect(rect: Rect, color: Scalar = ..., thickness: Thickness = ..., lineType: LineType = ...): Unit

Draws an axis-aligned rectangle. Mutates the receiver.

Draws an axis-aligned rectangle. Mutates the receiver.

Pass Thickness.Filled for a solid block — useful as a label background or for building a mask.

Attributes

Source
Draw.scala
def drawSegments(segments: Seq[Segment], color: Scalar = ..., thickness: Stroke = ..., lineType: LineType = ...): Unit

Draws every segment in segments. Mutates the receiver.

Draws every segment in segments. Mutates the receiver.

The renderer for houghLinesP, whose results are otherwise invisible.

Attributes

Source
Draw.scala
def drawText(text: String, at: Point, color: Scalar = ..., font: Font = ..., scale: Double = ..., thickness: Stroke = ..., lineType: LineType = ...): Unit

Draws text with its baseline's left end at at. Mutates the receiver.

Draws text with its baseline's left end at at. Mutates the receiver.

at is not the top-left corner: OpenCV anchors text on the baseline, so a y of 0 puts almost the whole string above the image and draws nothing visible. Draw.textSize gives the box to place it by.

Only the Hershey vector fonts exist — OpenCV cannot render a system font, and non-ASCII characters are drawn as ?.

Attributes

Source
Draw.scala
def fillPolygon(points: Seq[Point], color: Scalar = ..., lineType: LineType = ...): Unit

Fills the polygon described by points with color. Mutates the receiver.

Fills the polygon described by points with color. Mutates the receiver.

The outline is implicitly closed. Self-intersecting outlines are filled by OpenCV's even-odd rule.

Attributes

Source
Draw.scala
extension (mat: Mat)
def findContours(retrieval: ContourRetrieval = ..., approximation: ContourApproximation = ...): Seq[Contour]

Finds contours in a binary image.

Finds contours in a binary image.

The input must be single-channel 8-bit (or CV_32SC1); anything else raises CvError.NativeCall. Unlike the C++ API this does not modify mat — the Java binding copies internally — but treating a thresholded image as consumed is still the safer habit.

Every MatOfPoint OpenCV allocates, and the hierarchy Mat it fills, are released before this returns. The hierarchy itself is not exposed: it is only meaningful for the nesting-aware retrieval modes, and handing back a raw Nx1 CV_32SC4 Mat of indices would be exactly the untyped, unmanaged shape this library exists to remove. A typed nesting API can be added later without breaking this one.

Value parameters

approximation

how each outline is compressed. ContourApproximation.Simple collapses straight runs to their endpoints, so an axis-aligned rectangle comes back as 4 points rather than its full pixel chain.

retrieval

which contours to return and how to relate them. Defaults to ContourRetrieval.External — outermost only, which is what callers who ignore the hierarchy almost always mean.

Attributes

Returns

the contours, in OpenCV's order, as plain Scala data. Empty when the image is uniform.

Source
Contours.scala
extension (self: Mat)
def deskew(maxAngle: Double = ...): Managed[Mat]

Detects the dominant text skew and rotates the image upright — the classic OCR pre-step. Works on any image: it binarises internally to find the text pixels, fits a minimum-area rectangle to them, and rotates by that tilt. The exposed corners are filled white, and a detected skew beyond maxAngle is treated as a misread and left alone (a page of large graphics can fool the estimate).

Detects the dominant text skew and rotates the image upright — the classic OCR pre-step. Works on any image: it binarises internally to find the text pixels, fits a minimum-area rectangle to them, and rotates by that tilt. The exposed corners are filled white, and a detected skew beyond maxAngle is treated as a misread and left alone (a page of large graphics can fool the estimate).

Attributes

Source
Deskew.scala
extension (self: Mat)
def detailEnhance(strength: Float = ..., detail: Float = ...): Managed[Mat]

Detail enhancement — boosts local contrast and texture. Needs 8-bit 3-channel input.

Detail enhancement — boosts local contrast and texture. Needs 8-bit 3-channel input.

Attributes

Source
Effects.scala
def edgePreserving(strength: Float = ..., detail: Float = ...): Managed[Mat]

Edge-preserving smoothing — flattens texture while keeping edges (the basis of the painterly filters). Needs 8-bit 3-channel input.

Edge-preserving smoothing — flattens texture while keeping edges (the basis of the painterly filters). Needs 8-bit 3-channel input.

Attributes

Source
Effects.scala
def emboss: Managed[Mat]

Emboss, via a directional convolution.

Emboss, via a directional convolution.

Attributes

Source
Effects.scala
def gamma(g: Double): Managed[Mat]

Gamma correction: g < 1 darkens the mid-tones, g > 1 lifts them. Needs 8-bit 3-channel input — the same contract as its stylisation neighbours, enforced up front rather than as a CvError.NativeCall from Core.LUT on a float image.

Gamma correction: g < 1 darkens the mid-tones, g > 1 lifts them. Needs 8-bit 3-channel input — the same contract as its stylisation neighbours, enforced up front rather than as a CvError.NativeCall from Core.LUT on a float image.

Attributes

Source
Effects.scala
def pencilSketch(strength: Float = ..., detail: Float = ..., shade: Float = ...): Managed[Mat]

A colour pencil-sketch rendering. Needs 8-bit 3-channel input. The greyscale sketch OpenCV also computes is discarded — see pencilSketchBoth if you want it.

A colour pencil-sketch rendering. Needs 8-bit 3-channel input. The greyscale sketch OpenCV also computes is discarded — see pencilSketchBoth if you want it.

Attributes

Source
Effects.scala
def pencilSketchBoth(strength: Float = ..., detail: Float = ..., shade: Float = ...): PencilSketchPair

Both halves of a pencil sketch: the colour rendering and the greyscale one OpenCV computes on the way — the colour plate and the grey plate of the same drawing. pencilSketch pays for the grey output and throws it away (the native call always fills both destinations); this overload exists for callers that want the grey sketch too, so the work is never wasted. Needs 8-bit 3-channel input.

Both halves of a pencil sketch: the colour rendering and the greyscale one OpenCV computes on the way — the colour plate and the grey plate of the same drawing. pencilSketch pays for the grey output and throws it away (the native call always fills both destinations); this overload exists for callers that want the grey sketch too, so the work is never wasted. Needs 8-bit 3-channel input.

Both Mats in the returned pair are owned by the caller and must be released independently.

Attributes

Source
Effects.scala
def posterize(levels: Int): Managed[Mat]

Posterises to levels tones per channel.

Posterises to levels tones per channel.

Attributes

Source
Effects.scala
def saturate(factor: Double): Managed[Mat]

Adjusts saturation: factor > 1 is more vivid, &lt; 1 toward grey, 0 fully grey (still 3-channel). Needs 8-bit 3-channel input.

Adjusts saturation: factor > 1 is more vivid, &lt; 1 toward grey, 0 fully grey (still 3-channel). Needs 8-bit 3-channel input.

Attributes

Source
Effects.scala
def sepia: Managed[Mat]

Sepia tone, via a colour matrix. Needs 8-bit 3-channel input.

Sepia tone, via a colour matrix. Needs 8-bit 3-channel input.

Attributes

Source
Effects.scala
def stylize(strength: Float = ..., detail: Float = ...): Managed[Mat]

Stylisation — a smooth, painterly cartoon look via edge-aware smoothing. Needs 8-bit 3-channel input.

Stylisation — a smooth, painterly cartoon look via edge-aware smoothing. Needs 8-bit 3-channel input.

Attributes

Source
Effects.scala
def temperature(shift: Double): Managed[Mat]

Colour temperature: shift > 0 warms (more red), &lt; 0 cools (more blue), in [-1, 1]. Needs 8-bit 3-channel input.

Colour temperature: shift > 0 warms (more red), &lt; 0 cools (more blue), in [-1, 1]. Needs 8-bit 3-channel input.

Attributes

Source
Effects.scala
extension (self: Mat)
def absdiff(other: Mat): Managed[Mat]

Absolute per-element difference |self - other|. other is borrowed. The basis of frame-difference motion detection — see scalacv.vision.MotionDetector.

Absolute per-element difference |self - other|. other is borrowed. The basis of frame-difference motion detection — see scalacv.vision.MotionDetector.

Attributes

Source
Ops.scala
def adaptiveThreshold(maxValue: Double = ..., method: AdaptiveMethod = ..., blockSize: Int = ..., c: Double = ..., mode: Mode = ...): Managed[Mat]

Adaptive threshold — a threshold computed per neighbourhood rather than once for the whole image, which is what makes it hold up under uneven lighting (document scans, OCR pre-processing). CV_8UC1 only.

Adaptive threshold — a threshold computed per neighbourhood rather than once for the whole image, which is what makes it hold up under uneven lighting (document scans, OCR pre-processing). CV_8UC1 only.

mode is restricted to Threshold.Mode.Binary / Threshold.Mode.BinaryInv because OpenCV's adaptiveThreshold accepts exactly those two; it replaces the inverse: Boolean this parameter used to be — a boolean trap at the call site (inverse = true says nothing about what is inverted) when Threshold.Mode already models the distinction by name.

Value parameters

blockSize

the neighbourhood side; must be odd and ≥ 3.

c

a constant subtracted from the local mean/Gaussian — raise it to keep less.

Attributes

Source
Ops.scala
def addWeighted(alpha: Double, other: Mat, beta: Double, gamma: Double = ...): Managed[Mat]

Weighted sum: self * alpha + other * beta + gamma.

Weighted sum: self * alpha + other * beta + gamma.

other is borrowed, exactly like the receiver — it is neither released nor aliased.

Attributes

Source
Ops.scala
def bilateralFilter(diameter: Int, sigmaColor: Double, sigmaSpace: Double): Managed[Mat]

Edge-preserving bilateral filter: smooths flat regions while keeping edges crisp. Markedly slower than a Gaussian. diameter ≤ 0 lets OpenCV derive it from sigmaSpace.

Edge-preserving bilateral filter: smooths flat regions while keeping edges crisp. Markedly slower than a Gaussian. diameter ≤ 0 lets OpenCV derive it from sigmaSpace.

Attributes

Source
Ops.scala
def bitwiseNot(): Managed[Mat]

Bitwise NOT — inverts every pixel (255 - v for 8-bit).

Bitwise NOT — inverts every pixel (255 - v for 8-bit).

Attributes

Source
Ops.scala
def border(top: Int, bottom: Int, left: Int, right: Int, borderType: BorderType = ..., color: Scalar = ...): Managed[Mat]

Adds a border (padding) of the given pixel widths on each side.

Adds a border (padding) of the given pixel widths on each side.

Attributes

Source
Ops.scala
def boxBlur(kernel: Size, anchor: Point = ..., border: BorderType = ...): Managed[Mat]

Normalised box filter. anchor defaults to Point(-1, -1), OpenCV's spelling of "the kernel centre".

Normalised box filter. anchor defaults to Point(-1, -1), OpenCV's spelling of "the kernel centre".

Named boxBlur, not blur, on purpose: the high-level Image.blur is a radius-based Gaussian, and a mid-level method sharing that name would silently switch filter families (and output hash) the moment a caller drops from image.blur(2) to image.mat.blur(...). The two are different algorithms; the names say so.

border may not be BorderType.Wrap — see BorderType.requireFilterSupport.

Attributes

Source
Ops.scala
def canny(threshold1: Double, threshold2: Double, apertureSize: Int = ..., l2Gradient: Boolean = ...): Managed[Mat]

Canny edge detection. The result is always CV_8UC1 regardless of the source type.

Canny edge detection. The result is always CV_8UC1 regardless of the source type.

OpenCV accepts only 3, 5 and 7 for apertureSize — the Sobel aperture used internally — and aborts in native code for anything else, so it is checked here instead.

Attributes

Source
Ops.scala
def colorMap(map: Colormap): Managed[Mat]

Applies a false-colour map — turns a single-channel image (a depth map, a motion field, any data) into a colour heatmap. See Colormap.

Applies a false-colour map — turns a single-channel image (a depth map, a motion field, any data) into a colour heatmap. See Colormap.

Attributes

Source
Ops.scala
def convertScaleAbs(alpha: Double = ..., beta: Double = ...): Managed[Mat]

Scales, takes the absolute value, and saturating-casts to 8-bit unsigned.

Scales, takes the absolute value, and saturating-casts to 8-bit unsigned.

The companion to a OutputDepth.Signed16 sobel: it is what turns a signed derivative back into something displayable without losing the negative lobe.

Attributes

Source
Ops.scala
def cvtColor(conversion: ColorConversion): Managed[Mat]

Converts between colour spaces. The channel count of the result follows the conversion, not the source.

Converts between colour spaces. The channel count of the result follows the conversion, not the source.

Attributes

Source
Ops.scala
def dilate(radius: Int = ..., shape: MorphShape = ..., iterations: Int = ...): Managed[Mat]

Morphological dilation — grows bright regions, fills small dark gaps.

Morphological dilation — grows bright regions, fills small dark gaps.

Attributes

Source
Ops.scala
def equalizeHist(): Managed[Mat]

Histogram equalisation. OpenCV accepts CV_8UC1 only; anything else fails in native code.

Histogram equalisation. OpenCV accepts CV_8UC1 only; anything else fails in native code.

Attributes

Source
Ops.scala
def erode(radius: Int = ..., shape: MorphShape = ..., iterations: Int = ...): Managed[Mat]

Morphological erosion with a radius-derived structuring element — shrinks bright regions, removes small bright specks. iterations applies it repeatedly.

Morphological erosion with a radius-derived structuring element — shrinks bright regions, removes small bright specks. iterations applies it repeatedly.

Attributes

Source
Ops.scala
def extractChannel(index: Int): Managed[Mat]

Extracts a single channel as its own image.

Extracts a single channel as its own image.

Attributes

Source
Ops.scala
def flip(flip: Flip): Managed[Mat]

Mirrors the image across an axis — see Flip.

Mirrors the image across an axis — see Flip.

Attributes

Source
Ops.scala
def gaussianBlur(kernel: Size, sigmaX: Double = ..., sigmaY: Double = ..., border: BorderType = ...): Managed[Mat]

Gaussian blur.

Gaussian blur.

kernel may be Size(0, 0), in which case OpenCV derives the kernel from the sigmas; otherwise both extents must be positive and odd. A sigmaY of 0 means "same as sigmaX", which is OpenCV's own default and not a degenerate value.

border may not be BorderType.Wrap — see BorderType.requireFilterSupport.

Attributes

Source
Ops.scala
def inRange(lo: Scalar, hi: Scalar): Managed[Mat]

A binary mask (CV_8UC1, 0 or 255) of the pixels whose every channel lies within [lo, hi]. The core of colour segmentation — usually run on an HSV image. lo must not exceed hi in any channel; checked here, per extractChannel's index precheck, because OpenCV reports an inverted range only as an empty mask — a plausible-looking result that is silently wrong.

A binary mask (CV_8UC1, 0 or 255) of the pixels whose every channel lies within [lo, hi]. The core of colour segmentation — usually run on an HSV image. lo must not exceed hi in any channel; checked here, per extractChannel's index precheck, because OpenCV reports an inverted range only as an empty mask — a plausible-looking result that is silently wrong.

Attributes

Source
Ops.scala
def inpaint(mask: Mat, radius: Double = ...): Managed[Mat]

Inpaints the region under mask (CV_8UC1, non-zero = repair) from its surroundings — remove a scratch, an object, or a watermark. mask is borrowed.

Inpaints the region under mask (CV_8UC1, non-zero = repair) from its surroundings — remove a scratch, an object, or a watermark. mask is borrowed.

Attributes

Source
Ops.scala
def laplacian(kernelSize: Int = ..., depth: OutputDepth = ..., scale: Double = ..., delta: Double = ..., border: BorderType = ...): Managed[Mat]

Laplacian. kernelSize of 1 is the 3x3 aperture OpenCV special-cases, and is its default.

Laplacian. kernelSize of 1 is the 3x3 aperture OpenCV special-cases, and is its default.

border may not be BorderType.Wrap — see BorderType.requireFilterSupport.

Attributes

Source
Ops.scala
def masked(mask: Mat): Managed[Mat]

Keeps this image only where mask (CV_8UC1) is non-zero; the rest becomes black. mask is borrowed.

Keeps this image only where mask (CV_8UC1) is non-zero; the rest becomes black. mask is borrowed.

Attributes

Source
Ops.scala
def medianBlur(ksize: Int): Managed[Mat]

Median blur — each pixel becomes the median of its ksize×ksize neighbourhood. The standard cure for salt-and-pepper noise, and unlike a Gaussian it does not smear edges. ksize must be odd and ≥ 3.

Median blur — each pixel becomes the median of its ksize×ksize neighbourhood. The standard cure for salt-and-pepper noise, and unlike a Gaussian it does not smear edges. ksize must be odd and ≥ 3.

Attributes

Source
Ops.scala
def morphology(op: MorphOp, radius: Int = ..., shape: MorphShape = ..., iterations: Int = ...): Managed[Mat]

A compound morphological operation (open/close/gradient/top-hat/black-hat) — see MorphOp.

A compound morphological operation (open/close/gradient/top-hat/black-hat) — see MorphOp.

Attributes

Source
Ops.scala
def normalize(alpha: Double = ..., beta: Double = ..., depth: OutputDepth = ...): Managed[Mat]

Linearly rescales values into [alpha, beta] (min-max normalisation) and hands the result back at depth. Useful for stretching contrast, and the standard way of bringing a non-8-bit result — a disparity map, a distance transform, a float Sobel response — into a displayable range.

Linearly rescales values into [alpha, beta] (min-max normalisation) and hands the result back at depth. Useful for stretching contrast, and the standard way of bringing a non-8-bit result — a disparity map, a distance transform, a float Sobel response — into a displayable range.

depth defaults to OutputDepth.Unsigned8 rather than to OpenCV's own dtype = -1, which means "same depth as the source". With -1 a CV_32F input rescaled to [0, 255] comes back as a CV_32F holding the values 0..255, so the second half of the job — making it displayable — never happened: Image.toBufferedImage rejects it, applyColorMap (colorMap) aborts in native code because it takes CV_8UC1/CV_8UC3 only, and imwrite only survives it by silently coercing behind our back. For an already-8-bit source Unsigned8 and -1 are the same conversion, so a plain contrast stretch is unaffected by the default.

Pass OutputDepth.SameAsSource for a stretch that must keep the source's precision — rescaling a float image into [0, 1] for a model's input, for instance, where 8-bit would collapse the range onto 256 levels.

Attributes

Source
Ops.scala
def resize(size: Size, interpolation: Interpolation = ...): Managed[Mat]

Resizes to an absolute size, given here as a Size whose two Double extents are truncated toward zero on the way into native code: Size(1.9, 1.9) asks for a 1×1 image.

Resizes to an absolute size, given here as a Size whose two Double extents are truncated toward zero on the way into native code: Size(1.9, 1.9) asks for a 1×1 image.

That truncation is why the check below is on the truncated integers and not on the doubles. A computed target such as Size(width * factor, height * factor) with a small factor lands between 0 and 1, which is positive as a Double but empty as a cv::Size, and OpenCV then aborts with CV_Assert(inv_scale_x > 0) — a CvError.NativeCall quoting a C++ expression, in place of the IllegalArgumentException naming the caller's own argument that this file promises for a zero target size. Checking after truncation is what Mats.requireKernel already does for kernels.

Attributes

Source
Ops.scala
def rotate(rotation: Rotation): Managed[Mat]

A lossless quarter-turn rotation — exact pixels, no interpolation. See Rotation.

A lossless quarter-turn rotation — exact pixels, no interpolation. See Rotation.

Attributes

Source
Ops.scala
def rotated(degrees: Double, scale: Double = ..., interpolation: Interpolation = ..., border: BorderType = ..., color: Scalar = ...): Managed[Mat]

Rotates by an arbitrary angle (degrees, counter-clockwise) about the centre, expanding the canvas so no corner is clipped. scale zooms at the same time. The exposed border is filled per border.

Rotates by an arbitrary angle (degrees, counter-clockwise) about the centre, expanding the canvas so no corner is clipped. scale zooms at the same time. The exposed border is filled per border.

The fill is named color here just as in border, and the Constant default — where the filters default to BorderType.Reflect101 — is deliberate: a filter reflects so the kernel's support region stays inside the image content, which avoids edge ringing; a geometric transform exposes pixels that were never in the frame at all, and there a reflected or replicated edge would smear the image's own content into the border. A constant outside colour (black, or white for a scanned page) reads as background instead.

Attributes

Source
Ops.scala
def scaled(fx: Double, fy: Double, interpolation: Interpolation = ...): Managed[Mat]

Resizes by independent x and y scale factors. Rejects a pair of factors that would round this Mat's own size down to an empty one.

Resizes by independent x and y scale factors. Rejects a pair of factors that would round this Mat's own size down to an empty one.

A separate method rather than an overload because OpenCV distinguishes the two modes by passing Size(0, 0) — a sentinel that has no business in a typed API.

Positive factors are not on their own enough to know the call is legal: OpenCV derives the destination from the receiver as cvRound(cols * fx) × cvRound(rows * fy) and then asserts !dsize.empty(), so shrinking a small image hard enough (a 100-pixel sprite at fx = 0.005) dies in native code. The check therefore has to be against the receiver's extent, not against the factors.

math.rint and not .toInt or math.round, because cvRound rounds half to even: on a 100-wide source fx = 0.006 legitimately yields a 1-pixel result that truncation would reject, and fx = 0.025 yields 2 where math.round says 3. Note the asymmetry with resize, where the destination arrives as a cv::Size and is truncated instead — the two native paths genuinely round differently, so one shared rule would be wrong for one of them.

Attributes

Source
Ops.scala
def seamlessCloneInto(background: Mat, mask: Mat, center: Point): Managed[Mat]

Seamlessly clones this image (the foreground object) into background at center, blending gradients so the paste is invisible (Poisson editing). mask (CV_8UC1) marks the object; background and mask are borrowed. The result is background-sized.

Seamlessly clones this image (the foreground object) into background at center, blending gradients so the paste is invisible (Poisson editing). mask (CV_8UC1) marks the object; background and mask are borrowed. The result is background-sized.

Attributes

Source
Ops.scala
def sharpen(amount: Double = ...): Managed[Mat]

Unsharp-mask sharpening: adds back amount × (image − its blur). amount 0 is a no-op; ~1 is a firm sharpen. Overdo it and haloes appear at edges.

Unsharp-mask sharpening: adds back amount × (image − its blur). amount 0 is a no-op; ~1 is a firm sharpen. Overdo it and haloes appear at edges.

Attributes

Source
Ops.scala
def sobel(dx: Int, dy: Int, kernelSize: Int = ..., depth: OutputDepth = ..., scale: Double = ..., delta: Double = ..., border: BorderType = ...): Managed[Mat]

Sobel derivative.

Sobel derivative.

See OutputDepth before leaving depth at its default on an 8-bit image. border may not be BorderType.Wrap — see BorderType.requireFilterSupport.

Attributes

Source
Ops.scala
def threshold(value: Double, maxValue: Double = ..., kind: Threshold = ...): Thresholded

Thresholding.

Thresholding.

Returns a Thresholded — the thresholded image and the double OpenCV computed. Most wrappers drop that number; for Threshold.Auto.Otsu and Threshold.Auto.Triangle it is the threshold OpenCV chose, which is frequently the reason the call was made. For a fixed threshold it is just value handed back. A named pair, not a tuple, so .image chains with pipe like every other op.

Imgproc.threshold has a single 5-argument overload with no defaults, so every argument is spelled out here rather than being layered over Java defaults that do not exist.

Attributes

Source
Ops.scala
def undistorted(intrinsics: Intrinsics): Managed[Mat]

Removes lens distortion using calibrated camera Intrinsics — the barrel/pincushion bend a real lens adds is mapped back out, so straight edges in the world come back straight. A no-op (a plain copy) when intrinsics.distortion is empty. See scalacv.vision.Calibration.

Removes lens distortion using calibrated camera Intrinsics — the barrel/pincushion bend a real lens adds is mapped back out, so straight edges in the world come back straight. A no-op (a plain copy) when intrinsics.distortion is empty. See scalacv.vision.Calibration.

Attributes

Source
Ops.scala
extension (self: Managed[Mat])
def pipe(f: Mat => Managed[Mat]): Managed[Mat]

Hands the wrapped Mat to f and releases it once f has produced its own result.

Hands the wrapped Mat to f and releases it once f has produced its own result.

This is the whole reason the ownership contract above is safe to write down. Each op returns a Mat the caller owns, so a chain of them produces one owned Mat per stage, and every stage but the last is garbage the moment the next one returns. pipe makes that the default rather than something the caller has to remember: self is consumed, and using it afterwards throws IllegalStateException instead of reading freed memory.

val edges = src.gaussianBlur(Size(5, 5), 1.5).pipe(_.canny(50, 150))

The release happens in a finally, so a stage that throws does not leak its input either. For a terminal stage that produces something other than a Mat — a count, a Seq[Rect] — use Managed.use, which has the same shape and the same guarantee.

Attributes

Source
Ops.scala