java - 使用 OpenCV 修改 Mat 对象的像素值
问题描述
我是 Android 编程的初学者。我正在构建一个用于图像隐写术的 Android 应用程序。我已经使用 Java 和 OpenCV 为桌面开发了这个应用程序,它运行良好。我正在尝试重新使用我拥有的代码.
我创建了一个Mat
对象并将其传递给 Java 类(我已经拥有)。我能够读取Mat
对象中的像素强度,但是,当我尝试修改这些值(通过使用put()
)时,我的应用程序是崩溃。
抛出的异常是
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.hari.imagesteganography, PID: 8850
java.lang.UnsupportedOperationException: Provided data element number (3) should be multiple of the Mat channels count (4)
at org.opencv.core.Mat.put(Mat.java:954)
at com.example.hari.imagesteganography.LSBImageStego.encodeOriginalMessageBinaryLength(LSBImageStego.java:101)
at com.example.hari.imagesteganography.LSBImageStego.encodeImage(LSBImageStego.java:239)
at com.example.hari.imagesteganography.EncodeActivity$1.onClick(EncodeActivity.java:98)
at android.view.View.performClick(View.java:6302)
at android.view.View$PerformClick.run(View.java:24782)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6518)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
同样的方法 ( put()
) 在桌面上运行得非常好。
以下是我在 Android 应用程序中的代码。
private void encodeOriginalMessageBinaryLength(){
// LOGGING THIS,SHOWS THAT THE FUNCTION EXECUTION STARTED
Log.i("URI" , "encodeOriginalMessageBinaryLength()");
String binary_of_originalMessageBinaryLength = Integer.toBinaryString(this.originalMessageBinaryLength);
if(binary_of_originalMessageBinaryLength.length()%2 !=0){
binary_of_originalMessageBinaryLength = "0" + binary_of_originalMessageBinaryLength;
}
int remaining = binary_of_originalMessageBinaryLength.length();
String newLsbBits;
for(int col = this.coverImage_cols -1 ; col >=0 ; col--){
if(remaining > 0){
newLsbBits = binary_of_originalMessageBinaryLength.substring( remaining - NUMBER_OF_BITS_REPLACING , remaining );
remaining -= NUMBER_OF_BITS_REPLACING;
}else{
newLsbBits = String.join("", Collections.nCopies(NUMBER_OF_BITS_REPLACING, "0"));
}
Log.i("URI","newLsbBits"+newLsbBits);
String modifiedBinaryString = this.getBeautifiedBinaryString(this.coverImage.get( this.coverImage_rows -1,col )[0]).substring(0 , this.getBeautifiedBinaryString(this.coverImage.get( this.coverImage_rows -1,col )[0]).length() - NUMBER_OF_BITS_REPLACING) + newLsbBits;
Log.i("URI","modifiedBianryString"+modifiedBinaryString);
double[] data = new double[3];
data[0] = Integer.parseInt(modifiedBinaryString , 2);
data[1] = this.coverImage.get( this.coverImage_rows -1,col )[1];
data[2] = this.coverImage.get( this.coverImage_rows -1,col )[2];
this.coverImage_rows -1,col )[0]);
// LOGGING THE DIMENSIONS OF THE IMAGE CORRECTLY,SHOWS THAT THE Mat Object
// IS INITIALIZED CORRECTLY
Log.i("URI" , new Integer(this.coverImage_rows).toString());
Log.i("URI" , new Integer(this.coverImage_cols).toString());
// EXECUTING BELOW LINE CAUSES THE APP TO CRASH
this.coverImage.put( this.coverImage_rows -1,col , data);
// BELOW MESSAGE IS NOT BEING LOGGED
Log.i("URI" , "encodeOriginalMessageBinaryLength() END");
}
}
对应的Logcat日志如下。
2019-02-08 12:30:37.019 1230-1230/com.example.hari.imagesteganography I/URI: encodeOriginalMessageBinaryLength()
2019-02-08 12:30:37.019 1230-1230/com.example.hari.imagesteganography I/URI: newLsbBits10
2019-02-08 12:30:37.019 1230-1230/com.example.hari.imagesteganography I/URI: modifiedBianryString10010110
2019-02-08 12:30:37.019 1230-1230/com.example.hari.imagesteganography I/URI: 1440
2019-02-08 12:30:37.019 1230-1230/com.example.hari.imagesteganography I/URI: 2560
对象和Mat
其他属性设置如下
public LSBImageStego(Mat coverImage){
this.coverImage = coverImage;
this.coverImage_rows = (int)coverImage.size().height;
this.coverImage_cols = (int)coverImage.size().width;
}
我的代码错了吗?如何Mat
在 Android 中使用 OpenCV 和 Java 更改对象的像素强度值?
我相信,这个问题与Using get() and put() to access pixel values in OpenCV for Java
OR
opencv java modify pixel values不重复
,因为它们不适用于 Android,并且put()
这些问题中描述的方法有效即使在桌面上对我来说也很好。
解决方案
方法put()
在 Mat 类中被重载。对于每个 Mat 类型,都需要一个特定的数据类型。例如,如果你的 Mat 类型CV_32S
是 int [],则需要的数据是。您可以检查所有 Mat 类型的 Mat 类的实现。
推荐阅读
- rule-engine - 如何在 CLIPS 中存储一个函数,如 < 或 >= 作为稍后评估它的值?
- flutter - 如何从消费者中的提供者生成密钥?
- arrays - 在 Google 表格中将两列表转换为一个列表
- laravel - 在本地网络上共享代客泊车站点
- python - 如何定位列中值 1 之前的 5 行和之后的 5 行
- php - 如何从 WP 中的 ACF Image 字段的数组中获取信息?
- javascript - JavaScipt 中的输入处理
- python-3.x - Python:将数字列表列表转换为字符串列表
- swift - 使用 Swift 泛型调用非泛型库
- java - 如何在Java中删除某些已从玩家手中使用过的牌?