ThreeB 1.1
|
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