ThreeB 1.1

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

multispot5_jni.cc
Go to the documentation of this file.

    00001 /*
    00002     This file is part of B-cubed.
    00003
    00004     Copyright (C) 2009, 2010, 2011, Edward Rosten and Susan Cox
    00005
    00006     B-cubed is free software; you can redistribute it and/or
    00007     modify it under the terms of the GNU Lesser General Public
    00008     License as published by the Free Software Foundation; either
    00009     version 3.0 of the License, or (at your option) any later version.
    00010
    00011     This library is distributed in the hope that it will be useful,
    00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00014     Lesser General Public License for more details.
    00015
    00016     You should have received a copy of the GNU General Public License
    00017     along with this program.  If not, see <http://www.gnu.org/licenses/>
    00018 */
    00019
    00020 #include <sstream>
    00021 #include <algorithm>
    00022 #include <cvd/image.h>
    00023 #include <cvd/image_convert.h>
    00024
    00025 #include "ThreeBRunner.h"
    00026 #include "storm_imagery.h"
    00027 #include "multispot5.h"
    00028 #include "multispot5_place_choice.h"
    00029 #include "utility.h"
    00030 #include <gvars3/instances.h>
    00031
    00032 #include <tag/printf.h>
    00033 #undef make_tuple
    00034 #include <tr1/tuple>
    00035
    00036 using namespace std;
    00037 using namespace std::tr1;
    00038 using namespace CVD;
    00039 using namespace GVars3;
    00040 using namespace tag;
    00041 using namespace TooN;
    00042
    00043
    00044 /**
    00045 3B User interface for the Java plugin.
    00046
    00047 This particular UI ferries various messages between Java and C++
    00048 via callbacks and polling.
    00049
    00050 @ingroup gPlugin
    00051 */
    00052 class JNIUserInterface: public UserInterfaceCallback
    00053 {
    00054     private:
    00055         JNIEnv *env;
    00056         jobject ThreeBRunner_this;
    00057         jmethodID send_message_string;
    00058         jmethodID die;
    00059         jmethodID should_stop;
    00060         jmethodID send_new_points;
    00061         int passes;
    00062
    00063     public:
    00064         JNIUserInterface(JNIEnv* env_, jobject jthis)
    00065         :env(env_),ThreeBRunner_this(jthis)
    00066         {
    00067             jclass cls = env->GetObjectClass(jthis);
    00068
    00069             send_message_string  = env->GetMethodID(cls, "send_message_string", "(Ljava/lang/String;)V");
    00070             die  = env->GetMethodID(cls, "die", "(Ljava/lang/String;)V");
    00071
    00072             should_stop  = env->GetMethodID(cls, "should_stop", "()Z");
    00073
    00074             send_new_points = env->GetMethodID(cls, "send_new_points", "([F)V");
    00075
    00076             passes = GV3::get<int>("main.passes");
    00077         }
    00078
    00079
    00080         virtual void per_spot(int iteration, int pass, int spot_num, int total_spots)
    00081         {
    00082             send_message(sPrintf("Iteration %i, optimizing  %4i%%", iteration*passes+pass, 100 *spot_num / total_spots));
    00083         }
    00084
    00085         virtual void per_modification(int iteration, int spot_num, int total_spots)
    00086         {
    00087             send_message(sPrintf("Iteration %i, modifying  %4i%%", iteration*passes+passes-1, 100 *spot_num / total_spots));
    00088         }
    00089
    00090         virtual void per_pass(int , int , const std::vector<TooN::Vector<4> >& spots)
    00091         {
    00092             //Copy data into the correct format
    00093             vector<jfloat> pts_data;
    00094             for(unsigned int i=0; i < spots.size(); i++)
    00095             {
    00096                 pts_data.push_back(spots[i][2]);
    00097                 pts_data.push_back(spots[i][3]);
    00098             }
    00099
    00100             //Allocate a java array and copy data into it
    00101             jfloatArray pts = env->NewFloatArray(pts_data.size());
    00102             env->SetFloatArrayRegion(pts, 0, pts_data.size(), pts_data.data());
    00103
    00104             //Make the call...
    00105             jvalue pts_obj;
    00106             pts_obj.l = pts;
    00107
    00108             env->CallVoidMethod(ThreeBRunner_this, send_new_points, pts_obj);
    00109
    00110             //Free the object
    00111             env->DeleteLocalRef(pts);
    00112         }
    00113
    00114         virtual void perhaps_stop()
    00115         {
    00116             bool stop = env->CallBooleanMethod(ThreeBRunner_this, should_stop);
    00117             if(stop)
    00118                 throw UserIssuedStop();
    00119         }
    00120
    00121
    00122         void send_message(const string& s)
    00123         {
    00124             jvalue message_string;
    00125             message_string.l = env->NewStringUTF(s.c_str());
    00126             env->CallVoidMethod(ThreeBRunner_this, send_message_string, message_string);
    00127             env->DeleteLocalRef(message_string.l);
    00128         }
    00129
    00130         void fatal(const string& s)
    00131         {
    00132             jvalue message_string;
    00133             message_string.l = env->NewStringUTF(s.c_str());
    00134             env->CallVoidMethod(ThreeBRunner_this, die, message_string);
    00135             env->DeleteLocalRef(message_string.l);
    00136         }
    00137 };
    00138
    00139 ///Get a local C++ copy of a java string.
    00140 ///@ingroup gPlugin
    00141 string get_string(JNIEnv *env, jstring js)
    00142 {
    00143     const char* str;
    00144
    00145     //Covert the config into a string
    00146     str = env->GetStringUTFChars(js, NULL);
    00147
    00148     string stdstring(str);
    00149     env->ReleaseStringUTFChars(js, str);
    00150
    00151
    00152     return stdstring;
    00153 }
    00154
    00155 ///Get a local C++ copy of an image from a jbyteArray coming from the guts of ImageJ
    00156 ///@ingroup gPlugin
    00157 Image<jbyte> get_local_copy_of_image(JNIEnv* env, jbyteArray data, int rows, int cols)
    00158 {
    00159     //This takes a copy of the pixels (perhaps)
    00160     jbyte* pix = env->GetByteArrayElements(data, NULL);
    00161
    00162     BasicImage<jbyte> pix_im(pix, ImageRef(cols, rows));
    00163
    00164     Image<jbyte> im;
    00165     im.copy_from(pix_im);
    00166
    00167     //This frees the pixels if copied, or releases a reference
    00168     env->ReleaseByteArrayElements(data,pix, JNI_ABORT);
    00169
    00170     return im;
    00171 }
    00172
    00173 ///Get a local C++ copy of an image from a jfloatArray coming from the guts of ImageJ
    00174 ///@ingroup gPlugin
    00175 Image<float> get_local_copy_of_image(JNIEnv* env, jfloatArray data, int rows, int cols)
    00176 {
    00177     //This takes a copy of the pixels (perhaps)
    00178     float* pix = env->GetFloatArrayElements(data, NULL);
    00179
    00180     BasicImage<float> pix_im(pix, ImageRef(cols, rows));
    00181
    00182     Image<float> im;
    00183     im.copy_from(pix_im);
    00184
    00185     //This frees the pixels if copied, or releases a reference
    00186     env->ReleaseFloatArrayElements(data,pix, JNI_ABORT);
    00187
    00188     return im;
    00189 }
    00190
    00191
    00192 ///Run the 3B code.
    00193 ///@ingroup gPlugin
    00194 JNIEXPORT void JNICALL Java_ThreeBRunner_call
    00195   (JNIEnv *env, jobject jthis, jstring cfg, jobjectArray images, jbyteArray mask_data, jint n_images, jint rows, jint cols, jstring file)
    00196 {
    00197     istringstream config(get_string(env, cfg));
    00198     GUI.ParseStream(config);
    00199
    00200     JNIUserInterface ui(env, jthis);
    00201     ui.send_message("Initializing...");
    00202
    00203     string filename = get_string(env, file);
    00204
    00205     //Attmpt to open the file
    00206     ofstream save_spots;
    00207     save_spots.open(filename.c_str());
    00208     int err = errno;
    00209
    00210     if(!save_spots.good())
    00211     {
    00212         ui.fatal("failed to open " + filename + ": " + strerror(err));
    00213         return;
    00214     }
    00215
    00216     vector<ImageRef> maskir;
    00217     Image<double> maskd;
    00218     {
    00219         Image<jbyte> mask = get_local_copy_of_image(env, mask_data, rows, cols);
    00220         maskd = convert_image(mask);
    00221         for(ImageRef p(-1, 0); p.next(mask.size()); )
    00222             if(mask[p])
    00223                 maskir.push_back(p);
    00224     }
    00225
    00226
    00227     vector<Image<float> > ims;
    00228
    00229     for(int i=0; i < n_images; i++)
    00230     {
    00231         jfloatArray f = static_cast<jfloatArray>(env->GetObjectArrayElement(images, i));
    00232         ims.push_back(preprocess_image(get_local_copy_of_image(env, f, rows, cols)));
    00233         env->DeleteLocalRef(f);
    00234     }
    00235
    00236     double mean, variance;
    00237     tie(mean, variance) = mean_and_variance(ims);
    00238
    00239     for(unsigned int i=0; i < ims.size(); i++)
    00240             transform(ims[i].begin(), ims[i].end(), ims[i].begin(), bind1st(multiplies<double>(), 1/ sqrt(variance)));
    00241
    00242     tie(mean, variance) = mean_and_variance(ims);
    00243
    00244     //A sanity check.
    00245     cerr << "Rescaled:\n";
    00246     cerr << "mean = " << mean << endl;
    00247     cerr << "std  = " << sqrt(variance) << endl;
    00248     cerr << "Version 1.1" << endl;
    00249
    00250
    00251     auto_ptr<FitSpotsGraphics> gr = null_graphics();
    00252
    00253     place_and_fit_spots(ims, maskir, maskd, save_spots, *gr, ui);
    00254 }
    00255