4.0 Fundamental Image Manipulations and Transformations
This section moves beyond simple input and output to the core of image processing: altering the pixel values of an image to extract information, enhance features, or prepare it for further analysis. We will cover essential techniques such as converting between color spaces, segmenting an image through thresholding, performing geometric transformations like scaling and rotation, and annotating images by drawing shapes and text.
4.1 Color Space and Image Type Conversion
The imread() method includes an optional flags parameter that allows an image to be loaded directly into a different format. This is often more efficient than loading a color image and then converting it in a separate step.
The most common flags are constants defined in the Imgcodecs class:
| Flag Name | Description |
| IMREAD_COLOR | Loads the image as a 3-channel BGR (Blue-Green-Red) color image. This is the default. |
| IMREAD_GRAYSCALE | Loads the image and converts it to a single-channel grayscale image. |
| IMREAD_UNCHANGED | Loads the image as-is, including any alpha channel for transparency. |
Converting Colored Images to Grayscale
If you have already loaded a color image, you can convert it to another color space using the cvtColor() method from the Imgproc class. This method takes three primary arguments:
- src: The source Mat object.
- dst: The destination Mat object where the result will be stored.
- code: An integer constant specifying the conversion to perform. For color-to-grayscale, this is Imgproc.COLOR_RGB2GRAY.
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class ColorToGrayscale {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
String inputPath = “path/to/your/image.jpg”;
String outputPath = “path/to/your/grayscale_image.jpg”;
Mat src = Imgcodecs.imread(inputPath);
Mat dst = new Mat();
Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2GRAY);
Imgcodecs.imwrite(outputPath, dst);
System.out.println(“Image converted to grayscale and saved.”);
}
}
The output file will be a version of the original image rendered in shades of gray.
Converting Images to Binary
Binary images, which contain only black and white pixels, are often used in segmentation tasks to isolate objects of interest. This conversion is achieved through thresholding. The threshold() method from the Imgproc class applies a fixed-level threshold to each pixel.
Its key parameters are:
- src: The source image (typically grayscale).
- dst: The destination binary image.
- thresh: The threshold value. Any pixel with an intensity value above this will be assigned maxval.
- maxval: The new value assigned to pixels that exceed the threshold. For 8-bit images, this is typically 255 (white).
- type: The thresholding type, e.g., Imgproc.THRESH_BINARY.
Example: Color to Binary This example reads a color image and applies a threshold directly.
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class ColorToBinary {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
String inputPath = “path/to/your/image.jpg”;
String outputPath = “path/to/your/binary_from_color.jpg”;
Mat src = Imgcodecs.imread(inputPath);
Mat dst = new Mat();
Imgproc.threshold(src, dst, 127, 255, Imgproc.THRESH_BINARY);
Imgcodecs.imwrite(outputPath, dst);
System.out.println(“Color image converted to binary and saved.”);
}
}
Example: Grayscale to Binary This is the more common workflow, converting a grayscale image.
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class GrayScaleToBinary {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
String inputPath = “path/to/your/image.jpg”;
String outputPath = “path/to/your/binary_from_gray.jpg”;
Mat srcGray = Imgcodecs.imread(inputPath, Imgcodecs.IMREAD_GRAYSCALE);
Mat dst = new Mat();
Imgproc.threshold(srcGray, dst, 127, 255, Imgproc.THRESH_BINARY);
Imgcodecs.imwrite(outputPath, dst);
System.out.println(“Grayscale image converted to binary and saved.”);
}
}
In both cases, the output image will consist solely of black and white pixels, representing areas below and above the threshold value, respectively.
4.2 Geometric Transformations
Geometric transformations are operations that alter the spatial relationship between pixels in an image. They include common manipulations like scaling, rotation, and translation.
Scaling
Scaling is used to enlarge or shrink an image. The resize() method in Imgproc performs this operation. Its main parameters are:
- dsize: The desired output size as a Size object.
- fx, fy: Scaling factors along the horizontal and vertical axes. You can use these instead of dsize.
- interpolation: The algorithm used to calculate new pixel values (e.g., Imgproc.INTER_AREA).
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class Scaling {
public static void main(String args[]) {
System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
Mat src = Imgcodecs.imread(“path/to/your/image.jpg”);
Mat dst = new Mat();
Size size = new Size(src.cols() * 2, src.rows() * 2);
Imgproc.resize(src, dst, size, 0, 0, Imgproc.INTER_AREA);
Imgcodecs.imwrite(“path/to/your/scaled_image.jpg”, dst);
System.out.println(“Image Scaled and Saved”);
}
}
Rotation
Image rotation is a two-step process in OpenCV. First, a 2×3 rotation matrix is calculated using getRotationMatrix2D(). This matrix is then applied to the image using the warpAffine() method.
- getRotationMatrix2D(center, angle, scale): Defines the rotation.
- warpAffine(src, dst, rotationMatrix, size): Applies the transformation.
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class Rotation {
public static void main(String args[]) {
System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
Mat src = Imgcodecs.imread(“path/to/your/image.jpg”);
Mat dst = new Mat();
Point center = new Point(src.cols() / 2, src.rows() / 2);
Mat rotationMatrix = Imgproc.getRotationMatrix2D(center, 30, 1.0);
Size size = new Size(src.cols(), src.rows());
Imgproc.warpAffine(src, dst, rotationMatrix, size);
Imgcodecs.imwrite(“path/to/your/rotated_image.jpg”, dst);
System.out.println(“Image Rotated and Saved”);
}
}
Affine Translation
Affine translation shifts and deforms an image. Similar to rotation, it uses a transformation matrix, but this matrix is generated by getAffineTransform() based on the mapping of three corresponding points from the source to the destination image. The warpAffine() method then applies this transformation.
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.Point;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class AffineTranslation {
public static void main(String args[]) {
System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
Mat src = Imgcodecs.imread(“path/to/your/image.jpg”);
Mat dst = new Mat();
Point p1 = new Point( 0, 0 );
Point p2 = new Point( src.cols() – 1, 0 );
Point p3 = new Point( 0, src.rows() – 1 );
MatOfPoint2f srcPoints = new MatOfPoint2f(p1, p2, p3);
Point p4 = new Point( src.cols() * 0.0, src.rows() * 0.33 );
Point p5 = new Point( src.cols() * 0.85, src.rows() * 0.25 );
Point p6 = new Point( src.cols() * 0.15, src.rows() * 0.7 );
MatOfPoint2f dstPoints = new MatOfPoint2f(p4, p5, p6);
Mat transformMatrix = Imgproc.getAffineTransform(srcPoints, dstPoints);
Size size = new Size(src.cols(), src.rows());
Imgproc.warpAffine(src, dst, transformMatrix, size);
Imgcodecs.imwrite(“path/to/your/affine_image.jpg”, dst);
System.out.println(“Image Transformed and Saved”);
}
}
4.3 Drawing on Images
OpenCV provides a powerful suite of functions in the Imgproc class for annotating images. These functions modify the source Mat object directly, allowing you to draw various shapes and text to highlight features or convey information.
Drawing a Circle
The circle() method draws a circle on an image.
- Key Parameters: mat (image), center (Point), radius (int), color (Scalar), thickness (int).
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class DrawCircle {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat image = Imgcodecs.imread(“path/to/your/image.jpg”);
Imgproc.circle(
image,
new Point(image.cols()/2, image.rows()/2),
100,
new Scalar(0, 0, 255),
10
);
Imgcodecs.imwrite(“path/to/your/image_with_circle.jpg”, image);
System.out.println(“Drew circle on image.”);
}
}
Drawing a Line
The line() method draws a line segment between two points.
- Key Parameters: mat (image), pt1 (Point), pt2 (Point), color (Scalar), thickness (int).
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class DrawLine {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat image = Imgcodecs.imread(“path/to/your/image.jpg”);
Imgproc.line(
image,
new Point(10, 10),
new Point(image.cols() – 10, image.rows() – 10),
new Scalar(0, 0, 255),
5
);
Imgcodecs.imwrite(“path/to/your/image_with_line.jpg”, image);
System.out.println(“Drew line on image.”);
}
}
Drawing a Rectangle
The rectangle() method draws a rectangle defined by two opposite vertices.
- Key Parameters: mat (image), pt1 (Point), pt2 (Point), color (Scalar), thickness (int).
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class DrawRectangle {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat image = Imgcodecs.imread(“path/to/your/image.jpg”);
Imgproc.rectangle(
image,
new Point(50, 50),
new Point(image.cols() – 50, image.rows() – 50),
new Scalar(0, 255, 0),
5
);
Imgcodecs.imwrite(“path/to/your/image_with_rectangle.jpg”, image);
System.out.println(“Drew rectangle on image.”);
}
}
Drawing an Ellipse
The ellipse() method draws an ellipse inscribed within a rotated rectangle.
- Key Parameters: mat (image), box (RotatedRect), color (Scalar), thickness (int).
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.RotatedRect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class DrawEllipse {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat image = Imgcodecs.imread(“path/to/your/image.jpg”);
Imgproc.ellipse(
image,
new RotatedRect(
new Point(image.cols()/2, image.rows()/2),
new Size(260, 180),
45.0
),
new Scalar(255, 0, 0),
10
);
Imgcodecs.imwrite(“path/to/your/image_with_ellipse.jpg”, image);
System.out.println(“Drew ellipse on image.”);
}
}
Drawing Polylines
The polylines() method draws one or more polygonal curves.
- Key Parameters: mat (image), pts (List of MatOfPoint), isClosed (boolean), color (Scalar), thickness (int).
import java.util.ArrayList;
import java.util.List;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class DrawPolylines {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat image = Imgcodecs.imread(“path/to/your/image.jpg”);
List<MatOfPoint> pointsList = new ArrayList<>();
pointsList.add(new MatOfPoint(
new Point(50, 50), new Point(150, 100), new Point(250, 50), new Point(150, 150)
));
Imgproc.polylines(
image,
pointsList,
true, // isClosed
new Scalar(0, 255, 255),
3
);
Imgcodecs.imwrite(“path/to/your/image_with_polylines.jpg”, image);
System.out.println(“Drew polylines on image.”);
}
}
Drawing Convex Polylines
The fillConvexPoly() method draws a filled convex polygon.
- Key Parameters: mat (image), points (MatOfPoint), color (Scalar).
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class DrawConvexPoly {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat image = Imgcodecs.imread(“path/to/your/image.jpg”);
MatOfPoint matOfPoint = new MatOfPoint(
new Point(100, 100), new Point(200, 150),
new Point(150, 250), new Point(50, 200)
);
Imgproc.fillConvexPoly(
image,
matOfPoint,
new Scalar(0, 0, 255)
);
Imgcodecs.imwrite(“path/to/your/image_with_convexpoly.jpg”, image);
System.out.println(“Drew filled convex polygon on image.”);
}
}
Drawing Arrowed Lines
The arrowedLine() method draws a line segment with an arrowhead at one end.
- Key Parameters: mat (image), pt1 (Point, start), pt2 (Point, end with arrow), color (Scalar).
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class DrawArrow {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat image = Imgcodecs.imread(“path/to/your/image.jpg”);
Imgproc.arrowedLine(
image,
new Point(10, image.rows()/2),
new Point(image.cols() – 10, image.rows()/2),
new Scalar(0, 100, 255)
);
Imgcodecs.imwrite(“path/to/your/image_with_arrow.jpg”, image);
System.out.println(“Drew arrow on image.”);
}
}
Adding Text
The putText() method renders text on an image.
- Key Parameters: mat (image), text (String), org (Point, bottom-left corner), fontFace (int constant), fontScale (double), color (Scalar), thickness (int).
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class DrawText {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat image = Imgcodecs.imread(“path/to/your/image.jpg”);
Imgproc.putText(
image,
“OpenCV with Java”,
new Point(10, 50),
Core.FONT_HERSHEY_SIMPLEX,
1,
new Scalar(0, 0, 0),
4
);
Imgcodecs.imwrite(“path/to/your/image_with_text.jpg”, image);
System.out.println(“Drew text on image.”);
}
}
Having explored geometric and manual manipulations, we now move to automated, image-wide operations like filtering, which are used to reduce noise and enhance features.