Merge pull request #9406 from Cartucho:update_core_tutorials
commit
bc09d1ba3b
16 changed files with 1128 additions and 286 deletions
@ -0,0 +1,51 @@ |
|||||||
|
import org.opencv.core.*; |
||||||
|
import org.opencv.highgui.HighGui; |
||||||
|
import org.opencv.imgcodecs.Imgcodecs; |
||||||
|
|
||||||
|
import java.util.Locale; |
||||||
|
import java.util.Scanner; |
||||||
|
|
||||||
|
class AddingImagesRun{ |
||||||
|
public void run() { |
||||||
|
double alpha = 0.5; double beta; double input; |
||||||
|
|
||||||
|
Mat src1, src2, dst = new Mat(); |
||||||
|
|
||||||
|
System.out.println(" Simple Linear Blender "); |
||||||
|
System.out.println("-----------------------"); |
||||||
|
System.out.println("* Enter alpha [0.0-1.0]: "); |
||||||
|
Scanner scan = new Scanner( System.in ).useLocale(Locale.US); |
||||||
|
input = scan.nextDouble(); |
||||||
|
|
||||||
|
if( input >= 0.0 && input <= 1.0 ) |
||||||
|
alpha = input; |
||||||
|
|
||||||
|
//! [load]
|
||||||
|
src1 = Imgcodecs.imread("../../images/LinuxLogo.jpg"); |
||||||
|
src2 = Imgcodecs.imread("../../images/WindowsLogo.jpg"); |
||||||
|
//! [load]
|
||||||
|
|
||||||
|
if( src1.empty() == true ){ System.out.println("Error loading src1"); return;} |
||||||
|
if( src2.empty() == true ){ System.out.println("Error loading src2"); return;} |
||||||
|
|
||||||
|
//! [blend_images]
|
||||||
|
beta = ( 1.0 - alpha ); |
||||||
|
Core.addWeighted( src1, alpha, src2, beta, 0.0, dst); |
||||||
|
//! [blend_images]
|
||||||
|
|
||||||
|
//![display]
|
||||||
|
HighGui.imshow("Linear Blend", dst); |
||||||
|
HighGui.waitKey(0); |
||||||
|
//![display]
|
||||||
|
|
||||||
|
System.exit(0); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class AddingImages { |
||||||
|
public static void main(String[] args) { |
||||||
|
// Load the native library.
|
||||||
|
System.loadLibrary(Core.NATIVE_LIBRARY_NAME); |
||||||
|
new AddingImagesRun().run(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,186 @@ |
|||||||
|
import org.opencv.core.*; |
||||||
|
import org.opencv.core.Point; |
||||||
|
import org.opencv.highgui.HighGui; |
||||||
|
import org.opencv.imgproc.Imgproc; |
||||||
|
|
||||||
|
import java.util.*; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
class GeometricDrawingRun{ |
||||||
|
|
||||||
|
private static final int W = 400; |
||||||
|
|
||||||
|
public void run(){ |
||||||
|
//! [create_images]
|
||||||
|
/// Windows names
|
||||||
|
String atom_window = "Drawing 1: Atom"; |
||||||
|
String rook_window = "Drawing 2: Rook"; |
||||||
|
|
||||||
|
/// Create black empty images
|
||||||
|
Mat atom_image = Mat.zeros( W, W, CvType.CV_8UC3 ); |
||||||
|
Mat rook_image = Mat.zeros( W, W, CvType.CV_8UC3 ); |
||||||
|
//! [create_images]
|
||||||
|
|
||||||
|
//! [draw_atom]
|
||||||
|
/// 1. Draw a simple atom:
|
||||||
|
/// -----------------------
|
||||||
|
MyEllipse( atom_image, 90.0 ); |
||||||
|
MyEllipse( atom_image, 0.0 ); |
||||||
|
MyEllipse( atom_image, 45.0 ); |
||||||
|
MyEllipse( atom_image, -45.0 ); |
||||||
|
|
||||||
|
/// 1.b. Creating circles
|
||||||
|
MyFilledCircle( atom_image, new Point( W/2, W/2) ); |
||||||
|
//! [draw_atom]
|
||||||
|
|
||||||
|
//! [draw_rook]
|
||||||
|
/// 2. Draw a rook
|
||||||
|
/// ------------------
|
||||||
|
/// 2.a. Create a convex polygon
|
||||||
|
MyPolygon( rook_image ); |
||||||
|
|
||||||
|
//! [rectangle]
|
||||||
|
/// 2.b. Creating rectangles
|
||||||
|
Imgproc.rectangle( rook_image, |
||||||
|
new Point( 0, 7*W/8 ), |
||||||
|
new Point( W, W), |
||||||
|
new Scalar( 0, 255, 255 ), |
||||||
|
-1, |
||||||
|
8, |
||||||
|
0 ); |
||||||
|
//! [rectangle]
|
||||||
|
|
||||||
|
/// 2.c. Create a few lines
|
||||||
|
MyLine( rook_image, new Point( 0, 15*W/16 ), new Point( W, 15*W/16 ) ); |
||||||
|
MyLine( rook_image, new Point( W/4, 7*W/8 ), new Point( W/4, W ) ); |
||||||
|
MyLine( rook_image, new Point( W/2, 7*W/8 ), new Point( W/2, W ) ); |
||||||
|
MyLine( rook_image, new Point( 3*W/4, 7*W/8 ), new Point( 3*W/4, W ) ); |
||||||
|
//! [draw_rook]
|
||||||
|
|
||||||
|
/// 3. Display your stuff!
|
||||||
|
HighGui.imshow( atom_window, atom_image ); |
||||||
|
HighGui.moveWindow( atom_window, 0, 200 ); |
||||||
|
HighGui.imshow( rook_window, rook_image ); |
||||||
|
HighGui.moveWindow( rook_window, W, 200 ); |
||||||
|
|
||||||
|
HighGui.waitKey( 0 ); |
||||||
|
System.exit(0); |
||||||
|
} |
||||||
|
|
||||||
|
/// Function Declaration
|
||||||
|
|
||||||
|
/** |
||||||
|
* @function MyEllipse |
||||||
|
* @brief Draw a fixed-size ellipse with different angles |
||||||
|
*/ |
||||||
|
//! [my_ellipse]
|
||||||
|
private void MyEllipse( Mat img, double angle ) { |
||||||
|
int thickness = 2; |
||||||
|
int lineType = 8; |
||||||
|
int shift = 0; |
||||||
|
|
||||||
|
Imgproc.ellipse( img, |
||||||
|
new Point( W/2, W/2 ), |
||||||
|
new Size( W/4, W/16 ), |
||||||
|
angle, |
||||||
|
0.0, |
||||||
|
360.0, |
||||||
|
new Scalar( 255, 0, 0 ), |
||||||
|
thickness, |
||||||
|
lineType, |
||||||
|
shift ); |
||||||
|
} |
||||||
|
//! [my_ellipse]
|
||||||
|
/** |
||||||
|
* @function MyFilledCircle |
||||||
|
* @brief Draw a fixed-size filled circle |
||||||
|
*/ |
||||||
|
//! [my_filled_circle]
|
||||||
|
private void MyFilledCircle( Mat img, Point center ) { |
||||||
|
int thickness = -1; |
||||||
|
int lineType = 8; |
||||||
|
int shift = 0; |
||||||
|
|
||||||
|
Imgproc.circle( img, |
||||||
|
center, |
||||||
|
W/32, |
||||||
|
new Scalar( 0, 0, 255 ), |
||||||
|
thickness, |
||||||
|
lineType, |
||||||
|
shift ); |
||||||
|
} |
||||||
|
//! [my_filled_circle]
|
||||||
|
/** |
||||||
|
* @function MyPolygon |
||||||
|
* @function Draw a simple concave polygon (rook) |
||||||
|
*/ |
||||||
|
//! [my_polygon]
|
||||||
|
private void MyPolygon( Mat img ) { |
||||||
|
int lineType = 8; |
||||||
|
int shift = 0; |
||||||
|
|
||||||
|
/** Create some points */ |
||||||
|
Point[] rook_points = new Point[20]; |
||||||
|
rook_points[0] = new Point( W/4, 7*W/8 ); |
||||||
|
rook_points[1] = new Point( 3*W/4, 7*W/8 ); |
||||||
|
rook_points[2] = new Point( 3*W/4, 13*W/16 ); |
||||||
|
rook_points[3] = new Point( 11*W/16, 13*W/16 ); |
||||||
|
rook_points[4] = new Point( 19*W/32, 3*W/8 ); |
||||||
|
rook_points[5] = new Point( 3*W/4, 3*W/8 ); |
||||||
|
rook_points[6] = new Point( 3*W/4, W/8 ); |
||||||
|
rook_points[7] = new Point( 26*W/40, W/8 ); |
||||||
|
rook_points[8] = new Point( 26*W/40, W/4 ); |
||||||
|
rook_points[9] = new Point( 22*W/40, W/4 ); |
||||||
|
rook_points[10] = new Point( 22*W/40, W/8 ); |
||||||
|
rook_points[11] = new Point( 18*W/40, W/8 ); |
||||||
|
rook_points[12] = new Point( 18*W/40, W/4 ); |
||||||
|
rook_points[13] = new Point( 14*W/40, W/4 ); |
||||||
|
rook_points[14] = new Point( 14*W/40, W/8 ); |
||||||
|
rook_points[15] = new Point( W/4, W/8 ); |
||||||
|
rook_points[16] = new Point( W/4, 3*W/8 ); |
||||||
|
rook_points[17] = new Point( 13*W/32, 3*W/8 ); |
||||||
|
rook_points[18] = new Point( 5*W/16, 13*W/16 ); |
||||||
|
rook_points[19] = new Point( W/4, 13*W/16 ); |
||||||
|
|
||||||
|
MatOfPoint matPt = new MatOfPoint(); |
||||||
|
matPt.fromArray(rook_points); |
||||||
|
|
||||||
|
List<MatOfPoint> ppt = new ArrayList<MatOfPoint>(); |
||||||
|
ppt.add(matPt); |
||||||
|
|
||||||
|
Imgproc.fillPoly(img, |
||||||
|
ppt, |
||||||
|
new Scalar( 255, 255, 255 ), |
||||||
|
lineType, |
||||||
|
shift, |
||||||
|
new Point(0,0) ); |
||||||
|
} |
||||||
|
//! [my_polygon]
|
||||||
|
/** |
||||||
|
* @function MyLine |
||||||
|
* @brief Draw a simple line |
||||||
|
*/ |
||||||
|
//! [my_line]
|
||||||
|
private void MyLine( Mat img, Point start, Point end ) { |
||||||
|
int thickness = 2; |
||||||
|
int lineType = 8; |
||||||
|
int shift = 0; |
||||||
|
|
||||||
|
Imgproc.line( img, |
||||||
|
start, |
||||||
|
end, |
||||||
|
new Scalar( 0, 0, 0 ), |
||||||
|
thickness, |
||||||
|
lineType, |
||||||
|
shift ); |
||||||
|
} |
||||||
|
//! [my_line]
|
||||||
|
} |
||||||
|
|
||||||
|
public class BasicGeometricDrawing { |
||||||
|
public static void main(String[] args) { |
||||||
|
// Load the native library.
|
||||||
|
System.loadLibrary(Core.NATIVE_LIBRARY_NAME); |
||||||
|
new GeometricDrawingRun().run(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,109 @@ |
|||||||
|
import org.opencv.core.*; |
||||||
|
import org.opencv.highgui.HighGui; |
||||||
|
import org.opencv.imgcodecs.Imgcodecs; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
import java.util.*; |
||||||
|
|
||||||
|
class DiscreteFourierTransformRun{ |
||||||
|
private void help() { |
||||||
|
System.out.println("" + |
||||||
|
"This program demonstrated the use of the discrete Fourier transform (DFT). \n" + |
||||||
|
"The dft of an image is taken and it's power spectrum is displayed.\n" + |
||||||
|
"Usage:\n" + |
||||||
|
"./DiscreteFourierTransform [image_name -- default ../data/lena.jpg]"); |
||||||
|
} |
||||||
|
|
||||||
|
public void run(String[] args){ |
||||||
|
|
||||||
|
help(); |
||||||
|
|
||||||
|
String filename = ((args.length > 0) ? args[0] : "../data/lena.jpg"); |
||||||
|
|
||||||
|
Mat I = Imgcodecs.imread(filename, Imgcodecs.IMREAD_GRAYSCALE); |
||||||
|
if( I.empty() ) { |
||||||
|
System.out.println("Error opening image"); |
||||||
|
System.exit(-1); |
||||||
|
} |
||||||
|
|
||||||
|
//! [expand]
|
||||||
|
Mat padded = new Mat(); //expand input image to optimal size
|
||||||
|
int m = Core.getOptimalDFTSize( I.rows() ); |
||||||
|
int n = Core.getOptimalDFTSize( I.cols() ); // on the border add zero values
|
||||||
|
Core.copyMakeBorder(I, padded, 0, m - I.rows(), 0, n - I.cols(), Core.BORDER_CONSTANT, Scalar.all(0)); |
||||||
|
//! [expand]
|
||||||
|
|
||||||
|
//! [complex_and_real]
|
||||||
|
List<Mat> planes = new ArrayList<Mat>(); |
||||||
|
padded.convertTo(padded, CvType.CV_32F); |
||||||
|
planes.add(padded); |
||||||
|
planes.add(Mat.zeros(padded.size(), CvType.CV_32F)); |
||||||
|
Mat complexI = new Mat(); |
||||||
|
Core.merge(planes, complexI); // Add to the expanded another plane with zeros
|
||||||
|
//! [complex_and_real]
|
||||||
|
|
||||||
|
//! [dft]
|
||||||
|
Core.dft(complexI, complexI); // this way the result may fit in the source matrix
|
||||||
|
//! [dft]
|
||||||
|
|
||||||
|
// compute the magnitude and switch to logarithmic scale
|
||||||
|
// => log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2))
|
||||||
|
//! [magnitude]
|
||||||
|
Core.split(complexI, planes); // planes.get(0) = Re(DFT(I)
|
||||||
|
// planes.get(1) = Im(DFT(I))
|
||||||
|
Core.magnitude(planes.get(0), planes.get(1), planes.get(0));// planes.get(0) = magnitude
|
||||||
|
Mat magI = planes.get(0); |
||||||
|
//! [magnitude]
|
||||||
|
|
||||||
|
//! [log]
|
||||||
|
Mat matOfOnes = Mat.ones(magI.size(), magI.type()); |
||||||
|
Core.add(matOfOnes, magI, magI); // switch to logarithmic scale
|
||||||
|
Core.log(magI, magI); |
||||||
|
//! [log]
|
||||||
|
|
||||||
|
//! [crop_rearrange]
|
||||||
|
// crop the spectrum, if it has an odd number of rows or columns
|
||||||
|
magI = magI.submat(new Rect(0, 0, magI.cols() & -2, magI.rows() & -2)); |
||||||
|
|
||||||
|
// rearrange the quadrants of Fourier image so that the origin is at the image center
|
||||||
|
int cx = magI.cols()/2; |
||||||
|
int cy = magI.rows()/2; |
||||||
|
|
||||||
|
Mat q0 = new Mat(magI, new Rect(0, 0, cx, cy)); // Top-Left - Create a ROI per quadrant
|
||||||
|
Mat q1 = new Mat(magI, new Rect(cx, 0, cx, cy)); // Top-Right
|
||||||
|
Mat q2 = new Mat(magI, new Rect(0, cy, cx, cy)); // Bottom-Left
|
||||||
|
Mat q3 = new Mat(magI, new Rect(cx, cy, cx, cy)); // Bottom-Right
|
||||||
|
|
||||||
|
Mat tmp = new Mat(); // swap quadrants (Top-Left with Bottom-Right)
|
||||||
|
q0.copyTo(tmp); |
||||||
|
q3.copyTo(q0); |
||||||
|
tmp.copyTo(q3); |
||||||
|
|
||||||
|
q1.copyTo(tmp); // swap quadrant (Top-Right with Bottom-Left)
|
||||||
|
q2.copyTo(q1); |
||||||
|
tmp.copyTo(q2); |
||||||
|
//! [crop_rearrange]
|
||||||
|
|
||||||
|
magI.convertTo(magI, CvType.CV_8UC1); |
||||||
|
//! [normalize]
|
||||||
|
Core.normalize(magI, magI, 0, 255, Core.NORM_MINMAX, CvType.CV_8UC1); // Transform the matrix with float values
|
||||||
|
// into a viewable image form (float between
|
||||||
|
// values 0 and 255).
|
||||||
|
//! [normalize]
|
||||||
|
|
||||||
|
HighGui.imshow("Input Image" , I ); // Show the result
|
||||||
|
HighGui.imshow("Spectrum Magnitude", magI); |
||||||
|
HighGui.waitKey(); |
||||||
|
|
||||||
|
System.exit(0); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public class DiscreteFourierTransform { |
||||||
|
public static void main(String[] args) { |
||||||
|
// Load the native library.
|
||||||
|
System.loadLibrary(Core.NATIVE_LIBRARY_NAME); |
||||||
|
new DiscreteFourierTransformRun().run(args); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
from __future__ import print_function |
||||||
|
import sys |
||||||
|
|
||||||
|
import cv2 |
||||||
|
|
||||||
|
alpha = 0.5 |
||||||
|
|
||||||
|
print(''' Simple Linear Blender |
||||||
|
----------------------- |
||||||
|
* Enter alpha [0.0-1.0]: ''') |
||||||
|
if sys.version_info >= (3, 0): # If Python 3.x |
||||||
|
input_alpha = float(input()) |
||||||
|
else: |
||||||
|
input_alpha = float(raw_input()) |
||||||
|
if 0 <= alpha <= 1: |
||||||
|
alpha = input_alpha |
||||||
|
## [load] |
||||||
|
src1 = cv2.imread('../../../../data/LinuxLogo.jpg') |
||||||
|
src2 = cv2.imread('../../../../data/WindowsLogo.jpg') |
||||||
|
## [load] |
||||||
|
if src1 is None: |
||||||
|
print ("Error loading src1") |
||||||
|
exit(-1) |
||||||
|
elif src2 is None: |
||||||
|
print ("Error loading src2") |
||||||
|
exit(-1) |
||||||
|
## [blend_images] |
||||||
|
beta = (1.0 - alpha) |
||||||
|
dst = cv2.addWeighted(src1, alpha, src2, beta, 0.0) |
||||||
|
## [blend_images] |
||||||
|
## [display] |
||||||
|
cv2.imshow('dst', dst) |
||||||
|
cv2.waitKey(0) |
||||||
|
## [display] |
||||||
|
cv2.destroyAllWindows() |
@ -0,0 +1,115 @@ |
|||||||
|
import cv2 |
||||||
|
import numpy as np |
||||||
|
|
||||||
|
W = 400 |
||||||
|
## [my_ellipse] |
||||||
|
def my_ellipse(img, angle): |
||||||
|
thickness = 2 |
||||||
|
line_type = 8 |
||||||
|
|
||||||
|
cv2.ellipse(img, |
||||||
|
(W / 2, W / 2), |
||||||
|
(W / 4, W / 16), |
||||||
|
angle, |
||||||
|
0, |
||||||
|
360, |
||||||
|
(255, 0, 0), |
||||||
|
thickness, |
||||||
|
line_type) |
||||||
|
## [my_ellipse] |
||||||
|
## [my_filled_circle] |
||||||
|
def my_filled_circle(img, center): |
||||||
|
thickness = -1 |
||||||
|
line_type = 8 |
||||||
|
|
||||||
|
cv2.circle(img, |
||||||
|
center, |
||||||
|
W / 32, |
||||||
|
(0, 0, 255), |
||||||
|
thickness, |
||||||
|
line_type) |
||||||
|
## [my_filled_circle] |
||||||
|
## [my_polygon] |
||||||
|
def my_polygon(img): |
||||||
|
line_type = 8 |
||||||
|
|
||||||
|
# Create some points |
||||||
|
ppt = np.array([[W / 4, 7 * W / 8], [3 * W / 4, 7 * W / 8], |
||||||
|
[3 * W / 4, 13 * W / 16], [11 * W / 16, 13 * W / 16], |
||||||
|
[19 * W / 32, 3 * W / 8], [3 * W / 4, 3 * W / 8], |
||||||
|
[3 * W / 4, W / 8], [26 * W / 40, W / 8], |
||||||
|
[26 * W / 40, W / 4], [22 * W / 40, W / 4], |
||||||
|
[22 * W / 40, W / 8], [18 * W / 40, W / 8], |
||||||
|
[18 * W / 40, W / 4], [14 * W / 40, W / 4], |
||||||
|
[14 * W / 40, W / 8], [W / 4, W / 8], |
||||||
|
[W / 4, 3 * W / 8], [13 * W / 32, 3 * W / 8], |
||||||
|
[5 * W / 16, 13 * W / 16], [W / 4, 13 * W / 16]], np.int32) |
||||||
|
ppt = ppt.reshape((-1, 1, 2)) |
||||||
|
cv2.fillPoly(img, [ppt], (255, 255, 255), line_type) |
||||||
|
# Only drawind the lines would be: |
||||||
|
# cv2.polylines(img, [ppt], True, (255, 0, 255), line_type) |
||||||
|
## [my_polygon] |
||||||
|
## [my_line] |
||||||
|
def my_line(img, start, end): |
||||||
|
thickness = 2 |
||||||
|
line_type = 8 |
||||||
|
|
||||||
|
cv2.line(img, |
||||||
|
start, |
||||||
|
end, |
||||||
|
(0, 0, 0), |
||||||
|
thickness, |
||||||
|
line_type) |
||||||
|
## [my_line] |
||||||
|
## [create_images] |
||||||
|
# Windows names |
||||||
|
atom_window = "Drawing 1: Atom" |
||||||
|
rook_window = "Drawing 2: Rook" |
||||||
|
|
||||||
|
# Create black empty images |
||||||
|
size = W, W, 3 |
||||||
|
atom_image = np.zeros(size, dtype=np.uint8) |
||||||
|
rook_image = np.zeros(size, dtype=np.uint8) |
||||||
|
## [create_images] |
||||||
|
## [draw_atom] |
||||||
|
# 1. Draw a simple atom: |
||||||
|
# ----------------------- |
||||||
|
|
||||||
|
# 1.a. Creating ellipses |
||||||
|
my_ellipse(atom_image, 90) |
||||||
|
my_ellipse(atom_image, 0) |
||||||
|
my_ellipse(atom_image, 45) |
||||||
|
my_ellipse(atom_image, -45) |
||||||
|
|
||||||
|
# 1.b. Creating circles |
||||||
|
my_filled_circle(atom_image, (W / 2, W / 2)) |
||||||
|
## [draw_atom] |
||||||
|
## [draw_rook] |
||||||
|
|
||||||
|
# 2. Draw a rook |
||||||
|
# ------------------ |
||||||
|
# 2.a. Create a convex polygon |
||||||
|
my_polygon(rook_image) |
||||||
|
## [rectangle] |
||||||
|
# 2.b. Creating rectangles |
||||||
|
cv2.rectangle(rook_image, |
||||||
|
(0, 7 * W / 8), |
||||||
|
(W, W), |
||||||
|
(0, 255, 255), |
||||||
|
-1, |
||||||
|
8) |
||||||
|
## [rectangle] |
||||||
|
|
||||||
|
# 2.c. Create a few lines |
||||||
|
my_line(rook_image, (0, 15 * W / 16), (W, 15 * W / 16)) |
||||||
|
my_line(rook_image, (W / 4, 7 * W / 8), (W / 4, W)) |
||||||
|
my_line(rook_image, (W / 2, 7 * W / 8), (W / 2, W)) |
||||||
|
my_line(rook_image, (3 * W / 4, 7 * W / 8), (3 * W / 4, W)) |
||||||
|
## [draw_rook] |
||||||
|
cv2.imshow(atom_window, atom_image) |
||||||
|
cv2.moveWindow(atom_window, 0, 200) |
||||||
|
cv2.imshow(rook_window, rook_image) |
||||||
|
cv2.moveWindow(rook_window, W, 200) |
||||||
|
|
||||||
|
cv2.waitKey(0) |
||||||
|
cv2.destroyAllWindows() |
@ -0,0 +1,80 @@ |
|||||||
|
from __future__ import print_function |
||||||
|
import sys |
||||||
|
|
||||||
|
import cv2 |
||||||
|
import numpy as np |
||||||
|
|
||||||
|
|
||||||
|
def print_help(): |
||||||
|
print(''' |
||||||
|
This program demonstrated the use of the discrete Fourier transform (DFT). |
||||||
|
The dft of an image is taken and it's power spectrum is displayed. |
||||||
|
Usage: |
||||||
|
discrete_fourier_transform.py [image_name -- default ../../../../data/lena.jpg]''') |
||||||
|
|
||||||
|
|
||||||
|
def main(argv): |
||||||
|
|
||||||
|
print_help() |
||||||
|
|
||||||
|
filename = argv[0] if len(argv) > 0 else "../../../../data/lena.jpg" |
||||||
|
|
||||||
|
I = cv2.imread(filename, cv2.IMREAD_GRAYSCALE) |
||||||
|
if I is None: |
||||||
|
print('Error opening image') |
||||||
|
return -1 |
||||||
|
## [expand] |
||||||
|
rows, cols = I.shape |
||||||
|
m = cv2.getOptimalDFTSize( rows ) |
||||||
|
n = cv2.getOptimalDFTSize( cols ) |
||||||
|
padded = cv2.copyMakeBorder(I, 0, m - rows, 0, n - cols, cv2.BORDER_CONSTANT, value=[0, 0, 0]) |
||||||
|
## [expand] |
||||||
|
## [complex_and_real] |
||||||
|
planes = [np.float32(padded), np.zeros(padded.shape, np.float32)] |
||||||
|
complexI = cv2.merge(planes) # Add to the expanded another plane with zeros |
||||||
|
## [complex_and_real] |
||||||
|
## [dft] |
||||||
|
cv2.dft(complexI, complexI) # this way the result may fit in the source matrix |
||||||
|
## [dft] |
||||||
|
# compute the magnitude and switch to logarithmic scale |
||||||
|
# = > log(1 + sqrt(Re(DFT(I)) ^ 2 + Im(DFT(I)) ^ 2)) |
||||||
|
## [magnitude] |
||||||
|
cv2.split(complexI, planes) # planes[0] = Re(DFT(I), planes[1] = Im(DFT(I)) |
||||||
|
cv2.magnitude(planes[0], planes[1], planes[0])# planes[0] = magnitude |
||||||
|
magI = planes[0] |
||||||
|
## [magnitude] |
||||||
|
## [log] |
||||||
|
matOfOnes = np.ones(magI.shape, dtype=magI.dtype) |
||||||
|
cv2.add(matOfOnes, magI, magI) # switch to logarithmic scale |
||||||
|
cv2.log(magI, magI) |
||||||
|
## [log] |
||||||
|
## [crop_rearrange] |
||||||
|
magI_rows, magI_cols = magI.shape |
||||||
|
# crop the spectrum, if it has an odd number of rows or columns |
||||||
|
magI = magI[0:(magI_rows & -2), 0:(magI_cols & -2)] |
||||||
|
cx = int(magI_rows/2) |
||||||
|
cy = int(magI_cols/2) |
||||||
|
|
||||||
|
q0 = magI[0:cx, 0:cy] # Top-Left - Create a ROI per quadrant |
||||||
|
q1 = magI[cx:cx+cx, 0:cy] # Top-Right |
||||||
|
q2 = magI[0:cx, cy:cy+cy] # Bottom-Left |
||||||
|
q3 = magI[cx:cx+cx, cy:cy+cy] # Bottom-Right |
||||||
|
|
||||||
|
tmp = np.copy(q0) # swap quadrants (Top-Left with Bottom-Right) |
||||||
|
magI[0:cx, 0:cy] = q3 |
||||||
|
magI[cx:cx + cx, cy:cy + cy] = tmp |
||||||
|
|
||||||
|
tmp = np.copy(q1) # swap quadrant (Top-Right with Bottom-Left) |
||||||
|
magI[cx:cx + cx, 0:cy] = q2 |
||||||
|
magI[0:cx, cy:cy + cy] = tmp |
||||||
|
## [crop_rearrange] |
||||||
|
## [normalize] |
||||||
|
cv2.normalize(magI, magI, 0, 1, cv2.NORM_MINMAX) # Transform the matrix with float values into a |
||||||
|
## viewable image form(float between values 0 and 1). |
||||||
|
## [normalize] |
||||||
|
cv2.imshow("Input Image" , I ) # Show the result |
||||||
|
cv2.imshow("spectrum magnitude", magI) |
||||||
|
cv2.waitKey() |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
main(sys.argv[1:]) |
Loading…
Reference in new issue