美文网首页工作生活
opencv-实现图片的美容效果

opencv-实现图片的美容效果

作者: Peakmain | 来源:发表于2019-07-03 17:40 被阅读0次

文件放在xhdpi,xxhdpi,xxxhdpi哪个文件夹下更高效?

大家可以看我上篇文章Bitmap全面解析
理论:首先bitmap会开辟一个原图的内存,如果需要缩放会再开辟内存

放到当前主流的手机屏幕,现在主要是xxhdpi。此时native只会开辟一次内存

如果只放一个文件夹,会不会存在适配的问题?
不会,native层源码中有这行代码

  scale = (float) targetDensity / density;

targetDensity是手机的dpi,density是文件夹下的dpi,也就是说,它会根据你放的文件夹进行自动适配,比如xxhdpi的文件夹的图标尺寸是144* 144,你放到xhdpi文件夹(图标尺寸96* 96),当手机适配的时候,它会自动将图片转成144*144的

首先定以两个工具类,用来bitmap和mat之间互转

#include <jni.h>
#include <string>
#include <android/bitmap.h>
#include <malloc.h>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <android/log.h>

using namespace cv;
#define TAG "JNI_TAG"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)

/**
 * bitmap转成mat
 */

Mat bitmap2Mat(JNIEnv *env, jobject bitmap) {
    // 1. 获取图片的宽高,以及格式信息
    AndroidBitmapInfo info;
    AndroidBitmap_getInfo(env, bitmap, &info);
    void *pixels;
    AndroidBitmap_lockPixels(env, bitmap, &pixels);

    Mat mat;

    if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
        LOGE("nMatToBitmap: CV_8UC4 -> RGBA_8888");
        mat = Mat(info.height, info.width, CV_8UC4, pixels);
    } else {
        LOGE("nMatToBitmap: CV_8UC2 -> RGBA_565");
        mat = Mat(info.height, info.width, CV_8UC2, pixels);
    }

    AndroidBitmap_unlockPixels(env, bitmap);
    return mat;
}

/**
 * mat转成bitmap
 */
void mat2bitmap(JNIEnv *env, Mat src, jobject bitmap) {
    // 1. 获取图片的宽高,以及格式信息
    AndroidBitmapInfo info;
    AndroidBitmap_getInfo(env, bitmap, &info);
    void *pixels;
    AndroidBitmap_lockPixels(env, bitmap, &pixels);

    if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
        Mat tmp(info.height, info.width, CV_8UC4, pixels);
        if (src.type() == CV_8UC1) {
            LOGE("nMatToBitmap: CV_8UC1 -> RGBA_8888");
            cvtColor(src, tmp, COLOR_GRAY2RGBA);
        } else if (src.type() == CV_8UC3) {
            LOGE("nMatToBitmap: CV_8UC3 -> RGBA_8888");
            cvtColor(src, tmp, COLOR_RGB2RGBA);
        } else if (src.type() == CV_8UC4) {
            LOGE("nMatToBitmap: CV_8UC4 -> RGBA_8888");
            src.copyTo(tmp);
        }
    } else {
        // info.format == ANDROID_BITMAP_FORMAT_RGB_565
        Mat tmp(info.height, info.width, CV_8UC2, pixels);
        if (src.type() == CV_8UC1) {
            LOGE("nMatToBitmap: CV_8UC1 -> RGB_565");
            cvtColor(src, tmp, COLOR_GRAY2BGR565);
        } else if (src.type() == CV_8UC3) {
            LOGE("nMatToBitmap: CV_8UC3 -> RGB_565");
            cvtColor(src, tmp, COLOR_RGB2BGR565);
        } else if (src.type() == CV_8UC4) {
            LOGE("nMatToBitmap: CV_8UC4 -> RGB_565");
            cvtColor(src, tmp, COLOR_RGBA2BGR565);
        }
    }
    AndroidBitmap_unlockPixels(env, bitmap);
}

中值滤波:medianBlur

对所有考虑的点进行排序,取中间的值。主要用来去掉噪声图片
如下面这图上面的黑色点,就是噪声


c.jpg
 Mat src = bitmap2Mat(env, bitmap);
    Mat dest;
    medianBlur(src, dest, 7);

    //掩膜
    Mat final;
    Mat kernel;
    kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
    filter2D(dest,final,dest.depth(),kernel);
    mat2bitmap(env, final, bitmap);
image.png

双边滤波:bilateralFilter

主要用来图片美容,基于高斯模糊,高斯模糊保留轮廓并不强,双边保留轮廓信息会增强,基于高斯再增加像素差

腐蚀与膨胀

都是数学形态学,和卷积操作类似,用的是任意形状,矩形,椭圆形,最大值,最小值,中值等。主要用于处理黑白图片
erode:腐蚀,最小值
dilate:膨胀,最大值

   src = bitmap2Mat(env, bitmap);
    //创建一个kernel
    Mat kernel = getStructuringElement(MORPH_RECT, Size(15, 15));
    erode(src, dest, kernel);
    /*namedWindow("out_image");
    //动态控制
    createTrackbar("Trackbar", "out_image", &element_size, max_size,trackbarCallback);*/
    mat2bitmap(env, dest, bitmap);

相关文章

网友评论

    本文标题:opencv-实现图片的美容效果

    本文链接:https://www.haomeiwen.com/subject/kugqhctx.html