void WriteFile(const CImage& img, const char* filename) { // Determine the file extension const char *dot = strrchr(filename, '.'); if (strcasecmp(dot, ".tga") == 0 || strcasecmp(dot, ".tga") == 0) { if (img.PixType() == typeid(uchar)) WriteFileTGA(*(CByteImage *) &img, filename); else if(img.PixType() == typeid(float)) { CByteImage tmp(img.Shape()); TypeConvert(*(CFloatImage *) &img, tmp); WriteFileTGA(tmp, filename); } else { throw CError("Filetype not supported"); } } else if (strcasecmp(dot, ".jpg") == 0 || strcasecmp(dot, ".jpeg") == 0) { if (img.PixType() == typeid(uchar)) WriteFileJPEG(*(CByteImage *) &img, filename, 90); else if(img.PixType() == typeid(float)) { CByteImage tmp(img.Shape()); TypeConvert(*(CFloatImage *) &img, tmp); WriteFileJPEG(tmp, filename, 90); } else { throw CError("Filetype not supported"); } } else throw CError("WriteFile(%s): file type not supported", filename); }
void ReadFile(CImage& img, const char* filename) { // Determine the file extension const char *dot = strrchr(filename, '.'); if (strcasecmp(dot, ".tga") == 0 || strcasecmp(dot, ".tga") == 0) { if ((&img.PixType()) == 0) img.ReAllocate(CShape(), typeid(uchar), sizeof(uchar), true); if (img.PixType() == typeid(uchar)) ReadFileTGA(*(CByteImage *) &img, filename); else { CByteImage imgAux; ReadFileTGA(imgAux, filename); if(img.PixType() == typeid(float)) TypeConvert(imgAux, *(CFloatImage*) &img); else throw CError("Cannot load image into img with this type of buffer"); } } else if (strcasecmp(dot, ".jpg") == 0 || strcasecmp(dot, ".jpeg") == 0) { if ((&img.PixType()) == 0) img.ReAllocate(CShape(), typeid(uchar), sizeof(uchar), true); if (img.PixType() == typeid(uchar)) ReadFileJPEG(*(CByteImage *) &img, filename); else { CByteImage imgAux; ReadFileJPEG(imgAux, filename); if(img.PixType() == typeid(float)) TypeConvert(imgAux, *(CFloatImage*) &img); else throw CError("Cannot load image into img with this type of buffer"); } } else throw CError("ReadFile(%s): file type not supported", filename); }
CByteImage TinyImageFeatureExtractor::render(const Feature& f) const { CByteImage viz; TypeConvert(f, viz); return viz; }
Feature TinyImageFeatureExtractor::operator()(const CByteImage& img_) const { CFloatImage tinyImg(_targetW, _targetH, 1); /******** BEGIN TODO ********/ // Compute tiny image feature, output should be _targetW by _targetH a grayscale image // Steps are: // 1) Convert image to grayscale (see convertRGB2GrayImage in Utils.h) // 2) Resize image to be _targetW by _targetH // // Useful functions: // convertRGB2GrayImage, TypeConvert, WarpGlobal CByteImage gray; CFloatImage grayF; convertRGB2GrayImage(img_, gray); TypeConvert(gray, grayF); CTransform3x3 scale = CTransform3x3::Scale(1.* img_.Shape().width / _targetW, 1.* img_.Shape().height/ _targetH); WarpGlobal(grayF, tinyImg, scale, eWarpInterpLinear); /******** END TODO ********/ return tinyImg; }
CByteImage HOGFeatureExtractor::render(const Feature& f) const { CShape cellShape = _oriMarkers[0].Shape(); CFloatImage hogImgF(CShape(cellShape.width * f.Shape().width, cellShape.height * f.Shape().height, 1)); hogImgF.ClearPixels(); float minBinValue, maxBinValue; f.getRangeOfValues(minBinValue, maxBinValue); // For every cell in the HOG for(int hi = 0; hi < f.Shape().height; hi++) { for(int hj = 0; hj < f.Shape().width; hj++) { // Now _oriMarkers, multiplying contribution by bin level for(int hc = 0; hc < _nAngularBins; hc++) { float v = f.Pixel(hj, hi, hc) / maxBinValue; for(int ci = 0; ci < cellShape.height; ci++) { float* cellIt = (float*) _oriMarkers[hc].PixelAddress(0, ci, 0); float* hogIt = (float*) hogImgF.PixelAddress(hj * cellShape.height, hi * cellShape.height + ci, 0); for(int cj = 0; cj < cellShape.width; cj++, hogIt++, cellIt++) { (*hogIt) += v * (*cellIt); } } } } } CByteImage hogImg; TypeConvert(hogImgF, hogImg); return hogImg; }
// -------------------------------------------------------------------------------------------------------------------- // ObjectBinaryOp(): Registered to perform all operations involving objectc only values // -------------------------------------------------------------------------------------------------------------------- bool8 ObjectBinaryOp(CScriptContext* script_context, eOpCode op, eVarType& result_type, void* result_addr, eVarType val0_type, void* val0, eVarType val1_type, void* val1) { // -- sanity check if (!result_addr || !val0 || !val1) return (false); // -- ensure the types are converted to Type_object void* val0addr = TypeConvert(script_context, val0_type, val0, TYPE_object); void* val1addr = TypeConvert(script_context, val1_type, val1, TYPE_object); if (!val0addr || !val1addr) return (false); uint32 v0 = *(uint32*)val0addr; uint32 v1 = *(uint32*)val1addr; int32* result = (int32*)result_addr; result_type = TYPE_int; // -- perform the operation - note, both object handle values // -- can differ, but if neither object actually exists, they are equal switch (op) { case OP_CompareEqual: { CObjectEntry* oe0 = script_context->FindObjectEntry(v0); CObjectEntry* oe1 = script_context->FindObjectEntry(v1); *result = (oe0 == oe1) ? 0 : 1; return (true); } case OP_CompareNotEqual: { CObjectEntry* oe0 = script_context->FindObjectEntry(v0); CObjectEntry* oe1 = script_context->FindObjectEntry(v1); *result = (oe0 != oe1) ? 0 : 1; return (true); } } // -- fail return (false); }
// -------------------------------------------------------------------------------------------------------------------- // StringBinaryOp(): Registered to perform all numerical operations using a string that represents a float or an int // -------------------------------------------------------------------------------------------------------------------- bool8 StringBinaryOp(CScriptContext* script_context, eOpCode op, eVarType& result_type, void* result_addr, eVarType val0_type, void* val0, eVarType val1_type, void* val1) { // -- sanity check if (!script_context || !result_addr || !val0 || !val1) return (false); // -- if we cannot convert the string to a float non-zero value, convert it as an integer bool val0_float = true; void* val0addr = TypeConvert(script_context, val0_type, val0, TYPE_float); if (!val0addr || *(float32*)(val0addr) == 0.0f) { val0addr = TypeConvert(script_context, val0_type, val0, TYPE_int); val0_float = false; } bool val1_float = true; void* val1addr = TypeConvert(script_context, val1_type, val1, TYPE_float); if (!val1addr || *(float32*)(val1addr) == 0.0f) { val1addr = TypeConvert(script_context, val1_type, val1, TYPE_int); val1_float = false; } // -- ensure we at least got two numerical types if (!val0addr || !val1addr) return (false); // -- if either is a float, perform a float operation if (val0_float || val1_float) { return (FloatBinaryOp(script_context, op, result_type, result_addr, val0_float ? TYPE_float : TYPE_int, val0addr, val1_float ? TYPE_float : TYPE_int, val1addr)); } // -- else perform an integer op else { return (IntegerBinaryOp(script_context, op, result_type, result_addr, TYPE_int, val0addr, TYPE_int, val1addr)); } }
// -------------------------------------------------------------------------------------------------------------------- // BooleanBinaryOp(): Registered to perform all boolean operations using type bool // -------------------------------------------------------------------------------------------------------------------- bool8 BooleanBinaryOp(CScriptContext* script_context, eOpCode op, eVarType& result_type, void* result_addr, eVarType val0_type, void* val0, eVarType val1_type, void* val1) { // -- sanity check if (!script_context || !result_addr || !val0 || !val1) return (false); // -- ensure the types are converted to vector3f void* val0addr = TypeConvert(script_context, val0_type, val0, TYPE_bool); void* val1addr = TypeConvert(script_context, val1_type, val1, TYPE_bool); if (!val0addr || !val1addr) return (false); bool8* v0 = (bool8*)val0addr; bool8* v1 = (bool8*)val1addr; int32* result = (int32*)result_addr; result_type = TYPE_int; // -- the result for boolean operators is numerical... 1 == true, 0 == false // -- the result for comparison operators is numerical... (-1, 0, 1) for lt, eq, gt switch (op) { case OP_BooleanAnd: *result = *v0 && *v1 ? 1 : 0; return (true); case OP_BooleanOr: *result = *v0 || *v1 ? 1 : 0; return (true); case OP_CompareEqual: *result = *v0 == *v1 ? 0 : 1; return (true); case OP_CompareNotEqual: *result = *v0 != *v1 ? 0 : 1; return (true); } // -- fail return (false); }
NS_METHOD CNSAdapter_SecureJNIEnv::NewArray( /*[in]*/ jni_type element_type, /*[in]*/ jsize len, /*[out]*/ jarray* result) { if (m_pSecureEnv == NULL) return NS_ERROR_NULL_POINTER; jd_jni_type jd_element_type = TypeConvert(element_type); return m_pSecureEnv->NewArray(jd_element_type, len, result); }
NS_METHOD CNSAdapter_SecureJNIEnv::ReleaseArrayElements( /*[in]*/ jni_type element_type, /*[in]*/ jarray array, /*[in]*/ void *elems, /*[in]*/ jint mode) { if (m_pSecureEnv == NULL) return NS_ERROR_NULL_POINTER; jd_jni_type jd_element_type = TypeConvert(element_type); return m_pSecureEnv->ReleaseArrayElements(jd_element_type, array, elems, mode); }
NS_METHOD CNSAdapter_SecureJNIEnv::GetArrayElements( /*[in]*/ jni_type element_type, /*[in]*/ jarray array, /*[in]*/ jboolean *isCopy, /*[out]*/ void* result) { if (m_pSecureEnv == NULL) return NS_ERROR_NULL_POINTER; jd_jni_type jd_element_type = TypeConvert(element_type); return m_pSecureEnv->GetArrayElements(jd_element_type, array, isCopy, result); }
NS_METHOD CNSAdapter_SecureJNIEnv::SetArrayRegion( /*[in]*/ jni_type element_type, /*[in]*/ jarray array, /*[in]*/ jsize start, /*[in]*/ jsize len, /*[in]*/ void* buf) { if (m_pSecureEnv == NULL) return NS_ERROR_NULL_POINTER; jd_jni_type jd_element_type = TypeConvert(element_type); return m_pSecureEnv->SetArrayRegion(jd_element_type, array, start, len, buf); }
void WriteFileTGA(CImage img, const char* filename) { // Only 1, 3, or 4 bands supported CShape sh = img.Shape(); int nBands = sh.nBands; if (nBands != 1 && nBands != 3 && nBands != 4) throw CError("WriteFileTGA(%s): can only write 1, 3, or 4 bands", filename); // Only unsigned_8 supported directly #if 0 // broken for now if (img.PixType() != unsigned_8) { CImage u8img(sh, unsigned_8); TypeConvert(img, u8img); img = u8img; } #endif // Fill in the header structure CTargaHead h; memset(&h, 0, sizeof(h)); h.imageType = (nBands == 1) ? TargaRawBW : TargaRawRGB; // TODO: is TargaRawBW the right thing, or only binary? h.width = sh.width; h.height = sh.height; h.pixelSize = 8 * nBands; bool reverseRows = false; // TODO: when is this true? // Open the file and write the header FILE *stream = fopen(filename, "wb"); if (stream == 0) throw CError("WriteFileTGA: could not open %s", filename); if (fwrite(&h, sizeof(CTargaHead), 1, stream) != 1) throw CError("WriteFileTGA(%s): file is too short", filename); // Write out the rows for (int y = 0; y < sh.height; y++) { int yr = reverseRows ? sh.height-1-y : y; char* ptr = (char *) img.PixelAddress(0, yr, 0); int n = sh.width*sh.nBands; if (fwrite(ptr, sizeof(uchar), n, stream) != n) throw CError("WriteFileTGA(%s): file is too short", filename); } if (fclose(stream)) throw CError("WriteFileTGA(%s): error closing file", filename); }
/** * Set a static field on Java object in LiveConnect. * * @param type -- Return type * @param clazz -- Class object. * @param fieldID -- field id * @param val -- field value to set * @param ctx -- security context */ NS_METHOD CNSAdapter_SecureJNIEnv::SetStaticField( /*[in]*/ jni_type field_type, /*[in]*/ jclass clazz, /*[in]*/ jfieldID fieldID, /*[in]*/ jvalue val, /*[in]*/ nsISecurityContext* ctx ) { if (m_pSecureEnv == NULL) return NS_ERROR_NULL_POINTER; JDSmartPtr<ISecurityContext> spSecurityContext = new CNSAdapter_SecurityContextPeer(ctx); if (spSecurityContext == NULL) return NS_ERROR_OUT_OF_MEMORY; jd_jni_type jd_field_type = TypeConvert(field_type); return m_pSecureEnv->SetStaticField(jd_field_type, clazz, fieldID, val, spSecurityContext); }
/** * Get a field on Java object in LiveConnect. * * @param type -- Return type * @param obj -- Java object. * @param fieldID -- field id * @param result -- return field value * @param ctx -- security context */ NS_METHOD CNSAdapter_SecureJNIEnv::GetField( /*[in]*/ jni_type field_type, /*[in]*/ jobject obj, /*[in]*/ jfieldID fieldID, /*[out]*/ jvalue* result, /*[in]*/ nsISecurityContext* ctx) { if (m_pSecureEnv == NULL) return NS_ERROR_NULL_POINTER; JDSmartPtr<ISecurityContext> spSecurityContext = new CNSAdapter_SecurityContextPeer(ctx); if (spSecurityContext == NULL) return NS_ERROR_OUT_OF_MEMORY; jd_jni_type jd_field_type = TypeConvert(field_type); return m_pSecureEnv->GetField(jd_field_type, obj, fieldID, result, spSecurityContext); }
/** * Invoke static method on Java object in LiveConnect. * * @param type -- Return type * @param clazz -- Class object. * @param methodID -- method id * @param args -- arguments for invoking the constructor. * @param result -- return result of invocation. * @param ctx -- security context */ NS_METHOD CNSAdapter_SecureJNIEnv::CallStaticMethod( /*[in]*/ jni_type ret_type, /*[in]*/ jclass clazz, /*[in]*/ jmethodID methodID, /*[in]*/ jvalue *args, /*[out]*/ jvalue* result, /*[in]*/ nsISecurityContext* ctx ) { if (m_pSecureEnv == NULL) return NS_ERROR_NULL_POINTER; JDSmartPtr<ISecurityContext> spSecurityContext = new CNSAdapter_SecurityContextPeer(ctx); if (spSecurityContext == NULL) return NS_ERROR_OUT_OF_MEMORY; jd_jni_type jd_ret_type = TypeConvert(ret_type); return m_pSecureEnv->CallStaticMethod(jd_ret_type, clazz, methodID, args, result, spSecurityContext); }
Feature HOGFeatureExtractor::operator()(const CByteImage& img_) const { /******** BEGIN TODO ********/ // Compute the Histogram of Oriented Gradients feature // Steps are: // 1) Compute gradients in x and y directions. We provide the // derivative kernel proposed in the paper in _kernelDx and // _kernelDy. // 2) Compute gradient magnitude and orientation // 3) Add contribution each pixel to HOG cells whose // support overlaps with pixel. Each cell has a support of size // _cellSize and each histogram has _nAngularBins. // 4) Normalize HOG for each cell. One simple strategy that is // is also used in the SIFT descriptor is to first threshold // the bin values so that no bin value is larger than some // threshold (we leave it up to you do find this value) and // then re-normalize the histogram so that it has norm 1. A more // elaborate normalization scheme is proposed in Dalal & Triggs // paper but we leave that as extra credit. // // Useful functions: // convertRGB2GrayImage, TypeConvert, WarpGlobal, Convolve int xCells = ceil(1.*img_.Shape().width / _cellSize); int yCells = ceil(1.*img_.Shape().height / _cellSize); CFloatImage HOGHist(xCells, yCells, _nAngularBins); HOGHist.ClearPixels(); CByteImage gray(img_.Shape()); CFloatImage grayF(img_.Shape().width, img_.Shape().height, 1); convertRGB2GrayImage(img_, gray); TypeConvert(gray, grayF); CFloatImage diffX( img_.Shape()), diffY( img_.Shape()); Convolve(grayF, diffX, _kernelDx); Convolve(grayF, diffY, _kernelDy); CFloatImage grad(grayF.Shape()), grad2(grayF.Shape()); CFloatImage angl(grayF.Shape()), angl2(grayF.Shape()); for (int y = 0; y <grayF.Shape().height; y++){ for (int x = 0; x<grayF.Shape().width; x++) { grad2.Pixel(x,y,0) = (diffX.Pixel(x,y,0) * diffX.Pixel(x,y,0) + diffY.Pixel(x,y,0) * diffY.Pixel(x,y,0)); angl2.Pixel(x,y,0) = atan(diffY.Pixel(x,y,0) / abs(diffY.Pixel(x,y,0))); } } // Bilinear Filter ConvolveSeparable(grad2, grad, ConvolveKernel_121,ConvolveKernel_121,1); ConvolveSeparable(angl2, angl, ConvolveKernel_121,ConvolveKernel_121,1); //WriteFile(diffX, "angle.tga"); //WriteFile(diffY, "angleG.tga"); for (int y = 0; y <grayF.Shape().height; y++){ for (int x = 0; x<grayF.Shape().width; x++) { // Fit in the bins int a = angl.Pixel(x,y,0) / 3.14 * (_nAngularBins) + _nAngularBins/2; // Histogram HOGHist.Pixel(floor(1.*x / _cellSize), floor(1.*y / _cellSize), a) += grad.Pixel(x,y,0); } } // Normalization float threshold = 0.7; for (int y = 0; y < yCells; y++){ for (int x = 0; x < xCells; x++){ float total = 0; for (int a = 0; a < _nAngularBins; a++) { if (HOGHist.Pixel(x,y,a) > threshold) HOGHist.Pixel(x,y,a) = threshold; // Sum for normalization total += HOGHist.Pixel(x,y,a); } for (int a = 0;a< _nAngularBins; a++) { HOGHist.Pixel(x,y,a) /= total; } } } return HOGHist; /******** END TODO ********/ }
// -------------------------------------------------------------------------------------------------------------------- // IntegerBinaryOp(): Registered to perform all numerical operations involving integer only values // -------------------------------------------------------------------------------------------------------------------- bool8 IntegerBinaryOp(CScriptContext* script_context, eOpCode op, eVarType& result_type, void* result_addr, eVarType val0_type, void* val0, eVarType val1_type, void* val1) { // -- sanity check if (!result_addr || !val0 || !val1) return (false); // -- ensure the types are converted to vector3f void* val0addr = TypeConvert(script_context, val0_type, val0, TYPE_int); void* val1addr = TypeConvert(script_context, val1_type, val1, TYPE_int); if (!val0addr || !val1addr) return (false); int32* v0 = (int32*)val0addr; int32* v1 = (int32*)val1addr; int32* result = (int32*)result_addr; result_type = TYPE_int; // -- perform the operation switch (op) { case OP_Add: *result = *v0 + *v1; return (true); case OP_Sub: *result = *v0 - *v1; return (true); case OP_Mult: *result = *v0 * *v1; return (true); case OP_Div: if (*v1 == 0) { ScriptAssert_(script_context, false, "<internal>", -1, "Error - OP_Mod division by 0\n"); *result = 0; return (false); } *result = *v0 / *v1; return (true); case OP_Mod: if (*v1 == 0) { ScriptAssert_(script_context, false, "<internal>", -1, "Error - OP_Mod division by 0\n"); *result = 0; return (false); } *result = *v0 - ((*v0 / *v1) * *v1); return (true); // -- comparison operations (push a -1, 0, 1) for less than, equal, greater than case OP_CompareEqual: case OP_CompareNotEqual: case OP_CompareLess: case OP_CompareLessEqual: case OP_CompareGreater: case OP_CompareGreaterEqual: *result = *v0 - *v1; return (true); // -- Bit operations case OP_BitLeftShift: *result = *v0 << *v1; return (true); case OP_BitRightShift: *result = *v0 >> *v1; return (true); case OP_BitAnd: *result = *v0 & *v1; return (true); case OP_BitOr: *result = *v0 | *v1; return (true); case OP_BitXor: *result = *v0 ^ *v1; return (true); default: return false; } // -- fail return (false); }
// -------------------------------------------------------------------------------------------------------------------- // FloatBinaryOp(): Registered to perform all numerical operations involving a float, except vector3f scaling // -------------------------------------------------------------------------------------------------------------------- bool8 FloatBinaryOp(CScriptContext* script_context, eOpCode op, eVarType& result_type, void* result_addr, eVarType val0_type, void* val0, eVarType val1_type, void* val1) { // -- sanity check if (!script_context || !result_addr || !val0 || !val1) return (false); // -- ensure the types are converted to vector3f void* val0addr = TypeConvert(script_context, val0_type, val0, TYPE_float); void* val1addr = TypeConvert(script_context, val1_type, val1, TYPE_float); if (!val0addr || !val1addr) return (false); float32* v0 = (float32*)val0addr; float32* v1 = (float32*)val1addr; float32* result = (float32*)result_addr; result_type = TYPE_float; // -- perform the operation switch (op) { case OP_Add: *result = *v0 + *v1; return (true); case OP_Sub: *result = *v0 - *v1; return (true); case OP_Mult: *result = *v0 * *v1; return (true); case OP_Div: if (*v1 == 0.0f) { ScriptAssert_(script_context, false, "<internal>", -1, "Error - OP_Mod division by 0.0f\n"); *result = 0.0f; return (false); } *result = *v0 / *v1; return (true); case OP_Mod: if (*v1 == 0.0f) { ScriptAssert_(script_context, false, "<internal>", -1, "Error - OP_Mod division by 0.0f\n"); *result = 0.0f; return (false); } *result = *v0 - (float32)((int32)(*v0 / *v1) * *v1); return (true); // -- comparison operations (push a -1, 0, 1) for less than, equal, greater than case OP_CompareEqual: case OP_CompareNotEqual: case OP_CompareLess: case OP_CompareLessEqual: case OP_CompareGreater: case OP_CompareGreaterEqual: *result = (*v0 - *v1) < 0.0f ? -1.0f : (*v0 - *v1) == 0.0f ? 0.0f : 1.0f; return (true); default: return false; } // -- fail return (false); }