打开Cv滤镜在图像上显示黑色衬里

时间:2014-08-09 12:11:44

标签: c++ opencv image-processing android-ndk computer-vision

我正在使用open cv库为android创建过滤器,但它显示了我附加完整代码和快照的匿名结果。

结果图像如下:

enter image description here

原始图片如:

enter image description here

过滤器正在运行,但黑线不是我想要创建的结果。

Xml代码是:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:opencv="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000000" >

    <ImageView
            android:id="@+id/imageView1"
            android:layout_width="10dp"
            android:layout_height="10dp" />

    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true" />

</RelativeLayout>

MainActivity.java

private native int filter(int width, int height, int [] mPhotoIntArray,int [] nPhotoIntArray, int [] mCannyOutArray);
     static {
            System.loadLibrary("opencv");
          }
    ImageView img1;
    ImageView img2;
     @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        img1=(ImageView) findViewById(R.id.imageView1);
        img2=(ImageView) findViewById(R.id.imageView2);

       InputStream is;
       is = this.getResources().openRawResource(R.drawable.filter_image);
       Bitmap bmInImg = BitmapFactory.decodeStream(is);

       int [] mPhotoIntArray;
       int [] nPhotoIntArray;
       int [] mCannyOutArray;

       mPhotoIntArray = new int[bmInImg.getWidth() * bmInImg.getHeight()];
       // Copy pixel data from the Bitmap into the 'intArray' array
       bmInImg.getPixels(mPhotoIntArray, 0, bmInImg.getWidth(), 0, 0, bmInImg.getWidth(), bmInImg.getHeight());
         // create dummy buffer
        nPhotoIntArray = new int[bmInImg.getWidth() * bmInImg.getHeight()];
       //create result buffer
       mCannyOutArray = new int[bmInImg.getWidth() * bmInImg.getHeight()];



      filter(bmInImg.getHeight(), bmInImg.getWidth(), mPhotoIntArray, nPhotoIntArray,mCannyOutArray);

       //
       // Convert the result to Bitmap
       //
       Bitmap bmOutImg = Bitmap.createBitmap(bmInImg.getWidth(), bmInImg.getHeight(), Config.ARGB_8888);  
       bmOutImg.setPixels(mCannyOutArray, 0, bmInImg.getWidth(), 0, 0, bmInImg.getWidth(), bmInImg.getHeight());
       storeImage(bmOutImg, "Filter.PNG");

       img2.setImageBitmap(bmOutImg);


    }

OpenCvFilters.cpp

#include <jni.h>
#include <stdio.h>
#include "opencv2/core/core.hpp"
#include <opencv2/imgproc/imgproc.hpp>

using namespace std;
using namespace cv;

void blending_Lighten(Mat&img,Mat&ing, Mat &out);

extern "C" {
JNIEXPORT jint JNICALL Java_com_example_opencvfilters_MainActivity_filter(
        JNIEnv* env, jobject, jint width, jint height, jintArray in,jintArray inn,
        jintArray out) {
    jint* _in = env->GetIntArrayElements(in, 0);
    jint* _inn = env->GetIntArrayElements(inn, 0);
    jint* _out = env->GetIntArrayElements(out, 0);

    Mat mSrc(height, width, CV_8UC4, (unsigned char*) _in); // for input image
    Mat nSrc(height, width, CV_8UC4, (unsigned char*) _inn);
    Mat bgra(height, width, CV_8UC4, (unsigned char*) _out);
    blending_Lighten(mSrc,nSrc, bgra);
    jint retVal;
    int ret = 1;
    retVal = jint(retVal);
    return retVal;
}
}

void blending_Lighten(Mat& img1, Mat& img2, Mat& out)
{
    cv::Mat result(img1.size(), CV_32FC4);                    // result image is same size of input image

    // Img2 is the value of solid colors

    img2 = Mat(img1.size(), img1.type());
    vector<Mat> colors;
    split(img2, colors);//bgra
    colors[0] = 186;
    colors[1] = 44;
    colors[2] = 28;
    merge(colors, img2);

    // Iterate through rows , cols and colors(image channels)

    for (int i = 0; i < img1.rows; ++i){
        for (int j = 0; j < img1.cols; ++j){
            for (int c = 0; c<img1.channels(); c++){                // Iterate through colors
                //uchar target = img1.at<uchar>(i, 3*j+c);
                //uchar blend = img2.at<uchar>(i, 3*j+c);

                //Formula for lighten blending

                float target = float(img1.at<uchar>(i, 3 * j + c)) / 255.;
                float blend = float(img2.at<uchar>(i, 3 * j + c)) / 255.;
                result.at<float>(i, 3 * j + c) = max(target, blend);

            }
        }
    }
    result.convertTo(out, CV_8UC4, 255);
}

这是我完整且正常工作的代码,我只想删除图像上的黑线。

1 个答案:

答案 0 :(得分:4)

您的图片是四个频道。这意味着你的索引是错误的。在blending_Lighten()

            float target = float(img1.at<uchar>(i, 3 * j + c)) / 255.;
            float blend = float(img2.at<uchar>(i, 3 * j + c)) / 255.;
            result.at<float>(i, 3 * j + c) = max(target, blend);

应该是

            float target = float(img1.at<uchar>(i, 4 * j + c)) / 255.;
            float blend = float(img2.at<uchar>(i, 4 * j + c)) / 255.;
            result.at<float>(i, 4 * j + c) = max(target, blend);

顺便说一句,你没有用颜色设置alpha通道。

并且,似乎blending_Lighten()可以很好地简化:

void blending_Lighten(Mat& img1, Mat& img2, Mat& out)
{
    img2 = Mat(img1.size(), img1.type(), Scalar(186, 44, 28, 0));
    max(img1, img2, out);
}

最后,在从Java_com_example_opencvfilters_MainActivity_filter()返回之前,您应该致电env->ReleaseIntArrayElements(),查看您呼叫GetIntArrayElements()的所有内容。