简体   繁体   English

opencv java修改像素值

[英]opencv java modify pixel values

I've been trying to convert some opencv C++ code in opencv java and I can't seem to get pixel division to work properly.我一直在尝试在 opencv java 中转换一些 opencv C++ 代码,但似乎无法让像素分割正常工作。 I take a meanshiftsegmented mat that I convert to grayscale then to 32F.我拿了一个 meanshiftsegmented mat,然后转换为灰度,然后转换为 32F。

I then compare the most downsampled then upsampled image (which is comprised of the gray meanshift mat) to the original gray meanshift mat.然后我将最下采样然后上采样的图像(由灰色均值偏移垫组成)与原始灰色均值偏移垫进行比较。

I've already read Using get() and put() to access pixel values in OpenCV for Java我已经阅读了Using get() and put() to access pixel values in OpenCV for Java

however, it and others like it do not work.但是,它和其他类似的东西不起作用。 The error message I am getting is invalid mat type 5. However, even if I were able to see the saliency map I am positive it is wrong.我收到的错误消息是无效的垫子类型 5。但是,即使我能够看到显着图,我也肯定这是错误的。 This is because when I pass in image 001.jpg in c++ I am supposed to see the original image + red square around the objects.这是因为当我在 C++ 中传入图像 001.jpg 时,我应该看到原始图像 + 对象周围的红色方块。 In java, I am only seeing the original image at the end.在java中,我只看到最后的原始图像。

NOTE :笔记 :

AbstractImageProvider.deepCopy(AbstractImageProvider.matToBufferedImage(Saliency),disp); AbstractImageProvider.deepCopy(AbstractImageProvider.matToBufferedImage(Saliency),disp);

Is an API call that works when I attempt to show the original mat, meanShift mat, and the gray meanShift mat.是一个 API 调用,当我尝试显示原始垫、meanShift 垫和灰色 meanShift 垫时有效。 It fails at showing saliency.它无法显示显着性。

c++ C++

I only did a channel split because I was testing out other colorspaces, however in java I only want to use grayscale.我只做了一个通道拆分,因为我正在测试其他颜色空间,但是在 java 中我只想使用灰度。

  input = MeanShift.clone();
  input.convertTo(input, CV_32F);

  for(int i = 0; i < Pyramid_Size; i++){DS_Pyramid[i] = input.clone();}

  for (int i = 0; i < Pyramid_Size; i++){ 
    for (int k = 0; k <= i; k++){ // Why don't I just downsamplex3 a copy of MeanShift.clone then upsamplex3 that same one? ...
      pyrDown (DS_Pyramid[i], DS_Pyramid[i], Size(DS_Pyramid[i].cols/2, DS_Pyramid[i].rows/2));
      US_Pyramid[i] = DS_Pyramid[i].clone();
    }
    for (int j = 0; j <= i; j++){
      pyrUp (US_Pyramid[i], US_Pyramid[i], Size(US_Pyramid[i].cols*2, US_Pyramid[i].rows*2));
    }
  }

  top = US_Pyramid[Pyramid_Size - 1].clone(); // most down sampled layer, up sampled.
  split(top, top_chs);
  split(input.clone(), meanShift_chs); // split into channels result
  split(input.clone(), sal_chs); // holder to use for compare

  float top_min = 1.0;
  float ms_min = 1.0;
  for (int i = 0; i < top.rows; i++){   // find the smallest value in both top and meanShift
    for (int k = 0; k < top.cols; k++){ // this is so you can sub out the 0 with the min value
      for (int j = 0; j < top.channels(); j++){ // later on
    float a = top_chs[j].at<float>(i,k);
    float b = meanShift_chs[j].at<float>(i,k);
    if (a < top_min && a >= 0) {top_min = a;} // make sure you don't have a top_min of zero... that'd be bad.
    if (b < ms_min && b >= 0)  { ms_min = b;}
      }
    }
  }

  for (int i = 0; i < top.rows; i++){
    for (int k = 0; k < top.cols; k++){
      for (int j = 0; j < top.channels(); j++){
    float a,b,c;
    a = top_chs[j].at<float>(i,k);
    b = meanShift_chs[j].at<float>(i,k);

    if (a <= 0){a = top_min;} // make sure you don't divide by zero
    if (b <= 0){b = ms_min;} // make sure you really don't divide by zero
    if (a <= b){c = 1.0 - a/b;}
    else {c = 1.0 - b/a;}

    // c = sqrt(c); // makes stuff more salient, but makes noise pop out too
    sal_chs[j].at<float>(i,k) = c;
      }
    }
  }
  merge(sal_chs, Saliency); // combine into saliency map
  imshow("saliency", Saliency);

java爪哇

    MeanShift = inputImage.clone();

    Imgproc.pyrMeanShiftFiltering(MeanShift, MeanShift, MeanShift_spatialRad, MeanShift_colorRad);
    Imgproc.cvtColor(MeanShift, MeanShift, Imgproc.COLOR_BGR2GRAY);

    MeanShift.convertTo(MeanShift, CvType.CV_32F);                 // 32F between 0 - 1. ************** IMPORTANT LINE

    for (int i = 0; i < PyrSize; i++){
        DS_Pyramid.add(new Mat());
        UP_Pyramid.add(new Mat());
    }

    for (int i = 0; i < PyrSize; i++){    
        DS_Pyramid.set(i, MeanShift);
    }       

    for (int i = 0; i < PyrSize; i++){
        for(int k = 0; k <= i; k++){                               // At 0 is downsampled once, second twice, third 3 times. 
        Imgproc.pyrDown(DS_Pyramid.get(i), DS_Pyramid.get(i)); // pyrDown by default img.width / 2 img height / 2
        Mat a = new Mat();                                     // save the sampled down at i
        a = DS_Pyramid.get(i);                            
        UP_Pyramid.add(a);
        }
        for (int j = 0; j <= i; j++){
        Imgproc.pyrUp(UP_Pyramid.get(i),UP_Pyramid.get(i));    
        }                                                          
    }
    top = UP_Pyramid.get(PyrSize-1);
    bot = MeanShift.clone();
    Saliency = MeanShift.clone();


    //http://answers.opencv.org/question/5/how-to-get-and-modify-the-pixel-of-mat-in-java/
    //http://www.tutorialspoint.com/java_dip/applying_weighted_average_filter.htm

    for (int i = 0; i < top.rows(); i++){
        for (int j = 0; j < top.cols(); j++){
        int index = i * top.rows() + j;

        float[] top_temp = top.get(i, j);
        float[] bot_temp  = bot.get(i,j);
        float[] sal_temp = bot.get(i,j);

        if (top_temp[0] <= bot_temp[k]){sal_temp[0] = 1.0f - (top_temp[0]/bot_temp[0]);}
        else                           {sal_temp[0] = 1.0f - (bot_temp[0]/top_temp[0]);}

        Saliency.put(i,j, sal_temp);
        }
    }

    AbstractImageProvider.deepCopy(AbstractImageProvider.matToBufferedImage(Saliency),disp);

Found a simple and working solution after a lot of searching.经过大量搜索,找到了一个简单有效的解决方案。 This might help you get past the error- invalid mat type 5这可能会帮助您克服错误无效的垫子类型 5

Code:代码:

Mat img = Highgui.imread("Input.jpg"); //Reads image from the file system and puts into matrix
int rows = img.rows(); //Calculates number of rows
int cols = img.cols(); //Calculates number of columns
int ch = img.channels(); //Calculates number of channels (Grayscale: 1, RGB: 3, etc.)

for (int i=0; i<rows; i++)
{
    for (int j=0; j<cols; j++)
    {
        double[] data = img.get(i, j); //Stores element in an array
        for (int k = 0; k < ch; k++) //Runs for the available number of channels
        {
            data[k] = data[k] * 2; //Pixel modification done here
        }
        img.put(i, j, data); //Puts element back into matrix
    }
}
Highgui.imwrite("Output.jpg", img); //Writes image back to the file system using values of the modified matrix

Note: An important point that has not been mentioned anywhere online is that the method put does not write pixels onto Input.jpg .注意:在线任何地方都没有提到的重要一点是put方法不会将像素写入Input.jpg It merely updates the values of the matrix img .它只是更新矩阵img的值。 Therefore, the above code does not alter anything in the input image.因此,上面的代码不会改变输入图像中的任何内容。 For producing a visible output, the matrix img needs to be written onto a file ie, Output.jpg in this case.为了产生可见的输出,矩阵img需要写入一个文件,即在这种情况下的Output.jpg Also, using img.get(i, j) seems to be a better way of handling the matrix elements rather than using the accepted solution above as this helps in visualizing and working with the image matrix in a better way and does not require a large contiguous memory allocation.此外,使用img.get(i, j)似乎是处理矩阵元素的更好方法,而不是使用上面接受的解决方案,因为这有助于以更好的方式可视化和处理图像矩阵,并且不需要大量连续内存分配。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM