书籍名称:《王者归来 OpenCV3 Java 开发手册》
源码提交到了GitHub
改变每一个像素调整图片的明亮度
public static void main(String[] args) {
Mat src = Imgcodecs.imread("D://samples/lena.jpg");
Mat destination = new Mat(src.rows(),src.cols(),src.type());
for (int i = 0; i < src.rows(); i++) {
for (int j = 0; j < src.cols(); j++) {
double[] temp = src.get(i, j);
temp[0] = temp[0] * 2 + 30;
temp[1] = temp[1] * 2 + 30;
temp[2] = temp[2] * 2 + 30;
destination.put(i, j, temp);
}
}
new ShowImage(src);
new ShowImage(destination);
}
图片颜色相反
public static void main(String[] args) {
Mat src = Imgcodecs.imread("D://samples/lena.jpg");
Mat destination = new Mat(src.rows(),src.cols(),src.type(),new Scalar(255,255,255));
Mat dst = new Mat(src.rows(),src.cols(),src.type());
Core.bitwise_xor(src, destination, dst);
new ShowImage(dst);
}
//全白色Scalar(255,255,255)与原图相减就是相反的颜色。
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat src = Imgcodecs.imread("D://samples/lena.jpg");
Mat destination = new Mat(src.rows(),src.cols(),src.type(),new Scalar(255,255,255));
Mat dst = new Mat(src.rows(),src.cols(),src.type());
Core.subtract(destination, src, dst);
new ShowImage(dst);
}
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat src = Imgcodecs.imread("D://samples/lena.jpg");
Core.bitwise_not(src, src);
new ShowImage(src);
}
彩图变灰度图
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat src = Imgcodecs.imread("D://samples/lena.jpg");
Mat dst = new Mat(src.rows(),src.cols(),src.type());
Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2GRAY);
new ShowImage(dst);
}
模糊处理
GaussianBlur
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat src = Imgcodecs.imread("D://samples/lena.jpg");
Mat dst = new Mat(src.rows(),src.cols(),src.type());
Imgproc.GaussianBlur(src, dst, new Size(21,33), 0,0);
new ShowImage(src);
new ShowImage(dst);
}
medianBlur
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat src = Imgcodecs.imread("D://samples/lena.jpg");
Mat dst = new Mat(src.rows(),src.cols(),src.type());
Imgproc.medianBlur(src, dst, 25);
new ShowImage(dst);
}
boxFilter
static Mat BlurFilter(Mat src, int Ksize) {
Mat dst = new Mat(src.rows(),src.cols(),src.type());
Imgproc.boxFilter(src, dst, -1, new Size(Ksize,Ksize));
return dst;
}
blur
static Mat BlurFilter(Mat src, int KSize) {
Mat dst = new Mat(src.rows(),src.cols(),src.type());
Imgproc.blur(src, dst, new Size(KSize,KSize));
return dst ;
}
bilateralFilter
//双边模糊
private static Mat BlurFilter(Mat src, int d) {
Mat dst = new Mat(src.rows(),src.cols(),src.type());
Imgproc.bilateralFilter(src, dst, d, 120, 120);
return dst;
}
临界值处理
threshold
THRESH_BINARY
选定一个临界值,比如是125,则大于125的像素点的灰度值就会设定为最大值=255,反之小于125灰度值的设定为最小值=0。
THRESH_BINARY_INV
选定一个临界值,比如是125,则大于125的像素点的灰度值就会设定为最小值=0,其他小于125灰度值的就设定为最大值=255。
THRESH_TRUNC
可削弱数值较高的像素,如设定临界值为125,那小于125的像素保持不变,大于125的灰度值(比如255)的像素点就维持该临界值。
THRESH_TOZERO
假如设定临界值为125,如果图像的像素值小于125 的,一律变为0,大于125不进行改变。
THRESH_TOZERO_INV
设定临界值为125,如果图像的像素值小于125不进行改变,大于125则一律变为0。
adaptiveThreshold
void adaptiveThreshold(Mat src, Mat dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C)
maxValue : 最大值
adaptiveMethod : 临界值算法。其中:
ADAPTIVE_THRESH_MEAN_C
= 0 :使用平均加权ADAPTIVE_THRESH_GAUSSIAN_C
= 1 :使用高斯函数计算离中心点距离做加权处理。thresholdType : 临界值类型,两者互为相反。
THRESH_BINARY
= 0THRESH_BINARY_INV
= 1blockSize : 用于计算图像的 pixel 的临界值之临近区域大小,必须是奇数且大于 1。
锐利化处理
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat src = Imgcodecs.imread("D://samples/lena.jpg",Imgcodecs.CV_LOAD_IMAGE_COLOR);
Mat dst = new Mat(src.rows(),src.cols(),src.type());
Imgproc.medianBlur(src, dst, 9);
Core.addWeighted(src, 2.1, dst, -1.1, 0, dst);
new ShowImage(dst);
}
合并处理
/**
* 合并图像
* @param src1
* @param src2
* @param alpha 控制src1 的透明度
* @param beta 控制 src2 的透明度
* @param gamma 此值越大,合并的图像越明亮。
* @return
*/
static Mat merge(Mat src1, Mat src2, double alpha, double beta, double gamma) {
Mat dst = new Mat(src1.rows(),src1.cols(),src1.type());
Core.addWeighted(src1, alpha, src2, beta, gamma, dst);
return dst;
}
缩放处理
/**
* 放大
* @param src
* @return
*/
static Mat pyrUp(Mat src) {
Mat dst = new Mat(src.rows(),src.cols(),src.type());
Imgproc.pyrUp(src, dst,new Size(src.rows()*2,src.cols()*2));
return dst;
}
/**
* 缩小
* @param src
* @return
*/
static Mat pyrDown(Mat src) {
Mat dst = new Mat(src.rows(),src.cols(),src.type());
Imgproc.pyrDown(src, dst,new Size(src.rows()*0.5,src.cols()*0.5));
return dst;
}
static Mat resize(Mat src,double size) {
Mat dst = new Mat(src.rows(),src.cols(),src.type());
/**
* Imgproc.resize(src, dst, dsize, fx, fy, interpolation)
* fx:水平方向放大比例
* fy:垂直方向放大比例
* interpolation:插值的方式。以下:
* INTER_NEAREST = 0 :取临近点
* INTER_LINEAR=1 : 取临近 2*2 范围内的点使用线性处理
* INTER_AREA = 3 : 使用覆盖区的平均值
* INTER_CUBIC = 2 : 取 4*4 的范围内的点使用3次 cubic spline 处理
* INTER_LANCZOS4 =4 : 似乎差异不大。
*/
Imgproc.resize(src, dst, dst.size(), size, size, 0);
return dst ;
}
图像延展
static Mat resize(Mat src, double size) {
Mat dst = new Mat(src.rows()*(int)size,src.cols()*(int)size*2,src.type());
Imgproc.resize(src, dst, dst.size(), size, size, (int) (size*2));
return dst;
}
对比均衡
static Mat equalizeHise(Mat src) {
Mat dst = new Mat();
Imgproc.equalizeHist(src, dst);
return dst;
}
/**
* 彩色图像先用 split 分离 BGR等3个灰阶,再各自使用equalizeHist,最后用 merge合并。
* @param src
* @return
*/
static Mat equalizeHist(Mat src) {
Mat dst = new Mat();
List<Mat> mv = new ArrayList<>();
Core.split(src, mv);
Imgproc.equalizeHist(mv.get(0), mv.get(0));
Imgproc.equalizeHist(mv.get(1), mv.get(1));
Imgproc.equalizeHist(mv.get(2), mv.get(2));
Core.merge(mv, dst);
return dst;
}
static Mat merge(Mat src1, double alpha, double beta, double gamma) {
Mat dst = new Mat();
Mat src2 = new Mat(src1.rows(),src1.cols(),src1.type());
List<Mat> mv = new ArrayList<>();
Core.split(src1, mv);
Imgproc.equalizeHist(mv.get(0), mv.get(0));
Imgproc.equalizeHist(mv.get(1), mv.get(1));
Imgproc.equalizeHist(mv.get(2), mv.get(2));
Core.merge(mv, src2);
Core.addWeighted(src1, alpha, src2, beta, gamma, dst);
return dst;
}
/**
* Y: 明亮度
* U: 色度
* V: 浓度
* @param src
* @return
*/
static Mat equalizeHist(Mat src) {
Mat dst = new Mat();
Mat tempYUV = new Mat();
Imgproc.cvtColor(src, tempYUV, Imgproc.COLOR_RGB2YUV);
List<Mat> mv = new ArrayList<>();
Core.split(tempYUV, mv);
Imgproc.equalizeHist(mv.get(0), mv.get(0));
Core.merge(mv, dst);
Imgproc.cvtColor(src, dst, Imgproc.COLOR_YUV2RGB);
return dst;
}
/**
* double alpha = 0.5;
* double beta = 0.2;
* double gamma = 10;
*/
static Mat blurAndmerge(Mat src1, Mat src2, double alpha, double beta, double gamma, int GaussianKernelSize) {
Mat dst = new Mat();
Mat processBlur = new Mat(src1.rows(),src1.cols(),src1.type());
Imgproc.GaussianBlur(src1, processBlur, new Size(GaussianKernelSize, GaussianKernelSize), 0, 0);
Core.addWeighted(processBlur, alpha, src2, beta, gamma, dst);
return dst;
}
颜色空间
static Mat colorSpaceConversion(Mat src, int type) {
Mat dst = new Mat();
switch (type) {
case 1:
Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2HLS);
break;
case 2:
Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2BGR);
break;
case 3:
Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2HSV);
break;
case 4:
Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2Lab);
break;
case 5:
Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2Luv);
break;
case 6:
Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2YUV);
break;
case 7:
Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2YCrCb);
break;
case 8:
Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2XYZ);
break;
default:
break;
}
return dst;
}
堆叠处理
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat src = Imgcodecs.imread("D://samples/lena.jpg");
Mat hdst = new Mat();
Mat vdst = new Mat();
List<Mat> matList = new ArrayList<>();
//3次
matList.add(src);
matList.add(src);
matList.add(src);
Core.hconcat(matList , hdst);//产生水平图像堆叠
Core.vconcat(matList, vdst);//产生垂直图像堆叠
new ShowImage(hdst);
new ShowImage(vdst);
}
马赛克处理
/**
* 图像若是缩小或放大处理若干次,就会有马赛克效果
* @param args
*/
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat src = Imgcodecs.imread("D://samples/lena.jpg");
Imgproc.resize(src, src, new Size(), 0.1, 0.1, Imgproc.INTER_NEAREST);
Imgproc.resize(src, src, new Size(), 10.0, 10.0, Imgproc.INTER_NEAREST);
new ShowImage(src);
}
外框处理
static Mat addBoard(float borderSize, int borderType) {
Mat src = Imgcodecs.imread("D://samples/lena.jpg");
Mat dst = new Mat();
float top;
float bottom;
float left;
float right;
top = borderSize*src.rows();
bottom = borderSize*src.rows();
left = borderSize*src.cols();
right = borderSize * src.cols();
dst = src;
Core.copyMakeBorder(src, dst, (int)top, (int)bottom, (int)left, (int)right, borderType);
return dst;
}
ROI
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat src = Imgcodecs.imread("D://samples/lena.jpg",Imgcodecs.CV_LOAD_IMAGE_COLOR);
Mat src2 = Imgcodecs.imread("D://samples/jelly_studio_logo.jpg",Imgcodecs.CV_LOAD_IMAGE_COLOR);
Mat dst = src.clone();
//ROI :感兴趣的区域,简单来说就是要进行图像处理的区域。
//表示要在 src 图像中的(50,50)的地方放置 src2 这张图像(尺寸 90*62)
Rect roi = new Rect(50,50,90,62);
Mat dstROI = src.submat(roi); //表示要提取矩形子矩阵
src2.copyTo(dstROI,src2);
new ShowImage(src);
}
合并两个图像
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// 大图
Mat src = Imgcodecs.imread("D://samples/lena.jpg", Imgcodecs.CV_LOAD_IMAGE_COLOR);
// 小图
Mat src1 = Imgcodecs.imread("D://samples/jelly_studio_logo.jpg", Imgcodecs.CV_LOAD_IMAGE_COLOR);
Mat destination = src.clone();
Mat mask2 = new Mat();
Mat dst = new Mat();
Imgproc.cvtColor(src1, mask2, Imgproc.COLOR_BGR2GRAY);
Imgproc.threshold(mask2, mask2, 230, 255, Imgproc.THRESH_BINARY_INV);//像素点的值大于230的会被改变为0,其他就变为255
List<Mat> planes = new ArrayList<>();
List<Mat> result = new ArrayList<>();
Mat result1 = new Mat();
Mat result2 = new Mat();
Mat result3 = new Mat();
Core.split(src1, planes);
Core.bitwise_and(planes.get(0), mask2, result1);
Core.bitwise_and(planes.get(1), mask2, result2);
Core.bitwise_and(planes.get(2), mask2, result3);
new ShowImage(result3);
result.add(result1);
result.add(result2);
result.add(result3);
Core.merge(result, dst);
new ShowImage(dst);
// 以上白色变透明
// 再把小图 copy 到大图
Rect roi = new Rect(50, 50, 90, 62);// 不能比原图大,及小
Mat destinationROI = src.submat(roi);
dst.copyTo(destinationROI, dst);
new ShowImage(src);
}
使用核矩阵进行图像处理
Mean filter
static Mat Convolution(Mat source, int kernelSize) {
Mat kernel = Mat.ones(kernelSize, kernelSize,CvType.CV_32F);
for(int i = 0;i<kernel.rows();i++) {
for(int j = 0;j<kernel.cols();j++) {
double[] tmp = kernel.get(i, j);
tmp[0] = tmp[0] / (kernelSize * kernelSize);
kernel.put(i, j, tmp);
}
}
Mat destination = new Mat(source.rows(),source.cols(),source.type());
Imgproc.filter2D(source, destination, -1, kernel);
return destination;
}
Prewitt filter
static Mat Convolution(Mat source, int type) {
Mat kernel = Mat.ones(3, 3, CvType.CV_32F);
if (type == 1) {
kernel.put(0, 0, new float[] { -1, 0, 1 });
kernel.put(1, 0, new float[] { -1, 0, 1 });
kernel.put(2, 0, new float[] { -1, 0, 1 });
} else if (type == 2) {
kernel.put(0, 0, new float[] { -1, -1, -1 });
kernel.put(1, 0, new float[] { 0, 0, 0 });
kernel.put(1, 1, new float[] { 1, 1, 1 });
}
Mat destination = new Mat(source.rows(), source.cols(), source.type());
Imgproc.filter2D(source, destination, -1, kernel);
return destination;
}
Laplacian filter 1
static Mat Convolution(Mat source) {
Mat destination = new Mat(source.rows(),source.cols(),source.type());
Imgproc.Laplacian(source, destination, -1);
return destination;
}
Laplacian filter 2
// 1,12,35; 1,51,51
//ksize 要是奇数且不能大于31;scale控制轮廓明显度;delta控制明亮度;
static Mat Convolution(Mat source,int ksize,double scale,double delta) {
Mat destination = new Mat(source.rows(),source.cols(),source.type());
Imgproc.Laplacian(source, destination, -1,ksize,scale,delta);
return destination;
}