openCV操作像素的方式

前言

  • openCV操作像素的方式有十幾種,但常用的也就三種,今天就講解一下三種方式.

1.使用指針(像素數(shù)組): 優(yōu)點是速度快耗時少
2.迭代器 : 優(yōu)點是不會越界,安全性高
3.動態(tài)地址計算 : 優(yōu)點是理解方式和現(xiàn)實邏輯一樣,易于理解

今天通過一個改變圖片灰度值的例子,講解下操作像素的方式
我們知道,java 中圖片是ARGB格式表示,但在OpenCV中,圖片是以BGRA格式標(biāo)識,所以我們在使用時需要進(jìn)行變換.

將ARGB轉(zhuǎn)換為BGRA
Mat img(h, w, CV_8UC4, (unsigned char *) arr);

灰度圖 以數(shù)組存儲每個像素的數(shù)據(jù),每個數(shù)據(jù)叫做一個灰度值
將三個色值都改為 R*0.299+G*0.587+B*0.114 即 彩色轉(zhuǎn)黑白公式

Vec   4        b
向量  4通道   數(shù)據(jù)類型(b代表uchar)
  • 下面是布局文件
      <Button
            android:id="@+id/btn_change_gray"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="灰度變換"/>
        
      <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
  • 下面是主界面
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    static {
        System.loadLibrary("native-lib");
    }

    private Button btn_change_gray;
    private Bitmap bitmap;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);

       btn_change_gray = (Button) findViewById(R.id.btn_change_gray);
       btn_change_gray.setOnClickListener(this);
       bitmap = BitmapFactory.decodeResource(getResources(),   R.drawable.ds);
       iv.setImageBitmap(bitmap);
    }

     //改變圖片灰度值
    public native int[] change_gray(int[] arr, int w, int h);

    @Override
    public void onClick(View v) {
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();

        switch (v.getId()) {
            case R.id.btn_change_gray:

                int[] p = new int[w * h];
                bitmap.getPixels(p, 0, w, 0, 0, w, h);
                //調(diào)用native方法進(jìn)行圖片處理
                int[] result_gray = change_gray(p, w, h);
                Bitmap bitmap1 = Bitmap.createBitmap(w,h, Bitmap.Config.ARGB_8888);
                bitmap1.setPixels(result_gray,0,w,0,0,w,h);
                iv.setImageBitmap(bitmap1);

                break;
      }
    }
}
  • 下面是cpp文件
    #include <jni.h>
    #include <string>
    #include <opencv2/core/core.hpp>
    #include <opencv2/imgproc/imgproc.hpp>

    using namespace cv;
    using namespace std;

    extern "C"
    JNIEXPORT jintArray JNICALL
    Java_com_otitan_opencvdemo_MainActivity_change_1gray(JNIEnv *env, jobject jobj, jintArray arr_,
                                                     jint w, jint h) {
    jint *arr = env->GetIntArrayElements(arr_, NULL);
    if (arr == NULL) {
        return 0;
    }

    //將ARGB轉(zhuǎn)換為BGRA
    Mat img(h, w, CV_8UC4, (unsigned char *) arr);



    //----------------------------------------------------------------------------
    //第一種:指針的方式操作像素
    //圖片起始位置
     uchar *ptr = img.ptr(0);
     for (int i = 0; i < w * h; i++) {
         //R*0.299+G*0.587+B*0.114
         uchar GrayPixer = (uchar)(ptr[4 * i + 2] * 0.299 + ptr[4 *i + 1] * 0.587 + ptr[4 *i + 0] * 0.114);

         ptr[4 * i + 0] = GrayPixer;
         ptr[4 * i + 1] = GrayPixer;
         ptr[4 * i + 2] = GrayPixer;
     }
    //----------------------------------------------------------------------------


     //----------------------------------------------------------------------------
     //第二種:迭代器方式
     Mat_<Vec4b>::iterator it = img.begin<Vec4b>();
     Mat_<Vec4b>::iterator itend = img.end<Vec4b>();

     while (it != itend) {
         uchar temp = (*it)[2] * 0.299 + (*it)[1] * 0.587 + (*it)[0] * 0.114;
         (*it)[2] = temp;
         (*it)[1] = temp;
         (*it)[0] = temp;
         it++;
     }
    //----------------------------------------------------------------------------


    //----------------------------------------------------------------------------
    //第三種:動態(tài)地址計算
    int a = img.rows;//行
    int b = img.cols;//列

    for (int i = 0; i < a; ++i) {
        for (int j = 0; j < b; ++j) {
            uchar temp = img.at<Vec4b>(i, j)[2] * 0.229 +
                         img.at<Vec4b>(i, j)[1] * 0.587 +
                         img.at<Vec4b>(i, j)[0] * 0.114;

            img.at<Vec4b>(i, j)[2] = temp;
            img.at<Vec4b>(i, j)[1] = temp;
            img.at<Vec4b>(i, j)[0] = temp;
        }
    }

    //----------------------------------------------------------------------------

    int size = w * h;
    jintArray resultArray = env->NewIntArray(size);
    env->SetIntArrayRegion(resultArray, 0, size, arr);
    env->ReleaseIntArrayElements(arr_, arr, 0);
    return resultArray;
    }
  • 圖片處理結(jié)果
處理前
處理后
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容