Generate RGB to CMYK value in android - android

i want to generate RGB to CMYK value using this code
pixel = temp.getPixel(i,j);
R = Color.red(pixel);
G = Color.green(pixel);
B = Color.blue(pixel);
K = Math.min(Math.min(255-R, 255-G), 255-B);
if (K!=255){
c = ((255-R-K)/(255-K));
m = ((255-G-K)/(255-K));
y = ((255-B-K)/(255-K));
C = (int)(255*c);
M = (int)(255*m);
Y = (int)(255*y);
} else {
C = 255-R;
M = 255-G;
Y = 255-B;
}
The type of variabel pixel,R,G,B,K,C,M and Y are Integer. and the type of variabel c, m, and y are float. but when I show the result to the log cat like this,
Log.i("CMYK", String.valueOf(C)+" "+String.valueOf(M)+" "+String.valueOf(Y)+" "+String.valueOf(K));
Log.i("CMYK", String.valueOf(c)+" = ((255-"+String.valueOf(R)+"-"+String.valueOf(K)+")/(255-"+String.valueOf(K)+"))");
Log.i("CMYK", String.valueOf(m)+" = ((255-"+String.valueOf(G)+"-"+String.valueOf(K)+")/(255-"+String.valueOf(K)+"))");
Log.i("CMYK", String.valueOf(y)+" = ((255-"+String.valueOf(B)+"-"+String.valueOf(K)+")/(255-"+String.valueOf(K)+"))");
they give me this result of the log cat :
08-18 18:34:49.080: I/CMYK(819): 0 0 0 142
08-18 18:34:49.080: I/CMYK(819): 0.0 = ((255-90-142)/(255-142))
08-18 18:34:49.080: I/CMYK(819): 0.0 = ((255-113-142)/(255-142))
08-18 18:34:49.090: I/CMYK(819): 0.0 = ((255-99-142)/(255-142))
Just like the log say, value of R = 90, G = 113, and B = 99...
can anyone explain me why the mathematic result are 0??

If you use Integers then:
255-90-142 = 23
255-142 = 113
23 / 113 = 0 <-- becouse it's int
Same for rest of your code.

Related

pytorch KAIR example on Android

I stuck trying to trace/scipt ffdnet KAIR's model to android. Model's forward looks like:
def forward(self, x): #, paddingBottom, paddingRight): #, sigma):
noise_level_model = 15
sigma = torch.full((1, 1, 1, 1), noise_level_model / 255.).type_as(x)
h, w = x.size()[-2:]
paddingBottom = int(np.ceil(h/2)*2-h)
paddingRight = int(np.ceil(w/2)*2-w)
x = torch.nn.ReplicationPad2d((0, paddingRight, 0, paddingBottom))(x)
x = self.m_down(x)
# m = torch.ones(sigma.size()[0], sigma.size()[1], x.size()[-2], x.size()[-1]).type_as(x).mul(sigma)
m = sigma.repeat(1, 1, x.size()[-2], x.size()[-1])
x = torch.cat((x, m), 1)
x = self.model(x)
x = self.m_up(x)
x = x[..., :h, :w]
return x
If I trace that I get some warnings about padding arguments but model works on Android. Problem is that it isn't work with input of different sizes, only size same as 'test1.jpeg':
model_name = 'ffdnet_color'
model_pool = 'model_zoo'
model_path = os.path.join(model_pool, model_name + '.pth')
n_channels = 3
nc = 96
nb = 12
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = net(in_nc=n_channels, out_nc=n_channels, nc=nc, nb=nb, act_mode='R')
model.load_state_dict(torch.load(model_path), strict=True)
model.eval()
for k, v in model.named_parameters():
v.requires_grad = False
model = model.to(device)
img = 'testsets/myset/test1.jpeg'
img_name, ext = os.path.splitext(os.path.basename(img))
img_L = util.imread_uint(img, n_channels=n_channels)
img_L = util.uint2single(img_L)
noise_level_model = 15
img_L = util.single2tensor4(img_L)
img_L = img_L.to(device)
sigma_ = torch.full((1, 1, 1, 1), noise_level_model / 255)
sigma = torch.full((1, 1, 1, 1), noise_level_model / 255.).type_as(img_L)
traced_model = torch.jit.trace(model, img_L)
traced_optimized = optimize_for_mobile(traced_model)
save_path = os.path.splitext(os.path.basename(model_path))[0] + '-mobile.pth'
traced_optimized.save(save_path)
I've tried to script model with traced_model = torch.jit.script(model) but got errors:
TypeError: cannot create weak reference to 'numpy.ufunc' object
What should I do to achieve model works with different input size on mobile?
I encountered a similar issue. It was due to my model using numpy math operations (which are numpy.ufunc). I fixed the issue by replacing all of numpy ufuncs (i.e. np.add, np.ceil, and +, - etc on ndarrays) with corresponding torch versions (i.e. torch.add, torch.sub etc).

Tensorflow Lite - Input shape must be 5 dimensional error

I am trying to port a tensorflow model to tensorflow lite to use it in an android application. The conversion is successful and everything runs except for Internal error: Failed to run on the given Interpreter: input must be 5-dimensional. The input in the original model was input_shape=(20, 320, 240, 1), which is 20 320 x 240 grayscale images (therefore ...,1). Here is the important code:
List<Mat> preprocessedFrames = preprocFrames(buf);
//has length of 20 -> no problem there (shouldn't affect dimensionality either...)
int[] output = new int[2];
float[][][] inputMatrices = new float[preprocessedFrames.toArray().length][320][240];
for(int i = 0; i < preprocessedFrames.toArray().length; i++) {
Mat inpRaw = preprocessedFrames.get(i);
Bitmap data = Bitmap.createBitmap(inpRaw.cols(), inpRaw.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(inpRaw, data);
int[][] pixels = pixelsFromBitmap(data);
float[][] inputMatrix = inputMatrixFromIntPixels(pixels);
// returns float[][] with floats from 0 to 1
inputMatrices[i] = inputMatrix;
}
try{
detector.run(inputMatrices, output);
Debug("results: " + output.toString());
}
The model gives me an output of 2 neurons translating into 2 labels.
The model code is the following:
model = tf.keras.Sequential(name='detector')
model.add(tf.keras.layers.Conv3D(filters=(56), input_shape=(20, 320, 240, 1), strides=(2,2,2), kernel_size=(3,11,11), padding='same', activation="relu"))
model.add(tf.keras.layers.AveragePooling3D(pool_size=(1,4,4)))
model.add(tf.keras.layers.Conv3D(filters=(72), kernel_size=(4,7,7), strides=(1,2,2), padding='same'))
model.add(tf.keras.layers.Conv3D(filters=(81), kernel_size=(2,4,4), strides=(2,2,2), padding='same'))
model.add(tf.keras.layers.Conv3D(filters=(100), kernel_size=(1,2,2), strides=(3,2,2), padding='same'))
model.add(tf.keras.layers.Conv3D(filters=(128), kernel_size=(1,2,2), padding='same'))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(768, activation='tanh', kernel_regularizer=tf.keras.regularizers.l2(0.011)))
model.add(tf.keras.layers.Dropout(rate=0.1))
model.add(tf.keras.layers.Dense(256, activation='sigmoid', kernel_regularizer=tf.keras.regularizers.l2(0.012)))
model.add(tf.keras.layers.Dense(2, activation='softmax'))
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.00001), loss=tf.keras.losses.CategoricalCrossentropy(),
metrics=['accuracy'])
EDIT: I printed out the first input tensor as follows:
int[] shape = detector.getInputTensor(0).shape();
for(int r = 0; r < shape.length; r++){
Log.d("********" + r, "*******: " + r + " : " + shape[r]);
}
With that I first get the output [1,20,320,240,1]and after that I only get [20,320,240]. I am really quite desperate now...
So, I figured it out by myself and it seems like I really only had to make the input 5 dimensional by putting the content into a first dimension and every single pixel into a fifth dimension. I don't know why, but I will accept that xD.
float[][] output = new float[1][2];
float[][][][][] inputMatrices = new float[1][preprocessedFrames.toArray().length][320][240][1];
for(int i = 0; i < preprocessedFrames.toArray().length; i++) {
Mat inpRaw = preprocessedFrames.get(i);
Bitmap data = Bitmap.createBitmap(inpRaw.cols(), inpRaw.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(inpRaw, data);
int[][] pixels = pixelsFromBitmap(data);
float[][] inputMatrix = inputMatrixFromIntPixels(pixels);
for (int j = 0; j < inputMatrix.length - 1; j++) {
for(int k = 0; k < inputMatrix[0].length - 1; k++) {
inputMatrices[0][i][k][j][0] = inputMatrix[j][k];
}
}
}

Image to binary value - Pixel Value

I need to convert image to a hexadecimal value. When I try to get a color code of specific pixel on uiimage I got the wrong value. In Java I'm using bitmap.getpixel() method to reach pixel color and I'm getting correct value which is 255 but on swift same image pixel returning 0. Do you have any comment on this? or Is there a convenient way to convert image to a hexadecimal?
Java Code Reference
private func createPrintableObject (img:UIImage) -> String{
let sb = StringBuilder()
let height:Int = Int(img.size.height)
let width:Int = Int(img.size.width)
var index = 0
var rgb:Int,red:Int,green:Int,blue:Int
var rgbColor:UIColor
var auxBinaryChar: [Character] = ["0","0","0","0","0","0","0","0"]
widthBytes = width / 8
if(width % 8 > 0){
widthBytes = ((Int)(width/8))+1
}else{
widthBytes = width / 8
}
self.total = widthBytes * height
let pixelData = img.cgImage!.dataProvider!.data
let data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)
for h in 0...height-1 {
for w in 0...width-1 {
let value = Int(data[((width * w) + h) * 4])
//value returns in Java "-1" but In Swift returning "0"
// JAVA -> rgb = bitmapImage.getPixel(w, h); returning "-1"
red = (value >> 16) & 0x000000FF
green = (value >> 8) & 0x000000FF
blue = (value) & 0x000000FF
let totalColor = red + green + blue
var auxChar = "1"
if(totalColor > self.blackLimit){
auxChar = "0"
}
auxBinaryChar[index] = auxChar[0]
index+=1
if(index == 8 || w == (width-1)){
sb.append(self.fourByteBinary(binaryStr: String(auxBinaryChar)))
auxBinaryChar = ["0","0","0","0","0","0","0","0"]
index = 0
}
}
sb.append("\n")
}
return sb.toString()
}
private func fourByteBinary(binaryStr:String) -> String{
var decimal:Int = Int(binaryStr,radix: 2) ?? 0
if(decimal > 15){
return String(decimal, radix: 16, uppercase: true)
}else{
decimal = Int(String(decimal),radix:16) ?? 0
return "0" + String(decimal, radix: 16, uppercase: true)
}
}

Android dont print ARGB color like #c01c2112

Does Android not supporting printing the color like #c01c2112 with the format ARGB? It display error because of invalid color.
This part of my code is Store 1 and 0 into the arraylist.
ArrayList<String>arrayList = new ArrayList<>();
for(int a = 0; a < bitmap1.getWidth(); a++){
for(int b = 0; b < bitmap1.getHeight(); b++){
String a1 = String.valueOf(arrayInput1[a][b]);
String a2 = String.valueOf(arrayInput2[a][b]);
String a3 = String.valueOf(arrayInput3[a][b]);
String a4 = String.valueOf(arrayInput4[a][b]);
String a5 = String.valueOf(arrayInput5[a][b]);
String a6 = String.valueOf(arrayInput6[a][b]);
String a7 = String.valueOf(arrayInput7[a][b]);
String a8 = String.valueOf(arrayInput8[a][b]);
arrayList.add(a1+a2+a3+a4+a5+a6+a7+a8);
// Store 1110001 into ArrayList
}
}//End of nested For
Then here is the part to pass the data to an array.
String [] hexArrayRed = new String[arrayList.size()];
arrayList.toArray(hexArrayRed);
Then I input myself the #ff and the 0000 and combine with the data as I convert the data to hexadecimal value type. It is working fine here.
for(int a = 0; a < hexArrayRed.length; a++){
int dec = Integer.parseInt(String.valueOf(arrayList.get(a)),2);
String hexString = Integer.toString(dec, 16);
String alpha = "#ff";
String behind = "0000";
hexArrayRed[a] = alpha+hexString+behind;
/*
Red Hexadecimal Value --> #ff _ _ 0000
*/
}
Then there is the problem.
QRCodeWriter qwRed = new QRCodeWriter();
try {
HashMap<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
hints.put(EncodeHintType.MARGIN, 2);
BitMatrix matrix = qwRed.encode(finalText,
BarcodeFormat.QR_CODE,
bitmap1.getWidth(),
bitmap1.getHeight(),
hints);
//START OF RED
final Bitmap newBitmapRed = Bitmap.createBitmap(
bitmap1.getWidth(),
bitmap1.getHeight(),
Bitmap.Config.ARGB_8888
);
int counter1 = 0;
for (int a = 0; a < bitmap1.getWidth(); a++) {
for (int b = 0; b < bitmap1.getHeight(); b++) {
//int c = 0;
int[] color = new int[hexArrayRed.length];
color[counter1] = Color.parseColor(hexArrayRed[counter1]); //Error is right here
int d = matrix.get(a,b)? color[counter1]: Color.WHITE;
newBitmapRed.setPixel(a,b,d);
counter1++;
}
}
//END OF RED
Then I get the error of printing the unknown color.
Process: kopilim.scs.prototyping, PID: 9890
java.lang.IllegalArgumentException: Unknown color
Is it the Android dont support color like #f212cc12 some sort like this the ARGB color?
Your code of converting from binary to decimal to hex works fine, except for one tiny part.
The problem is related to this part of your code:
String hexString = Integer.toString(dec, 16);
The problem with using Integer.toString() is that it'll give you the integer as a String, without the extra 0 padding.
What I mean by this is, for example: if your binary String was 00000111. Using Integer.parseInt("00000111", 2); would give you a decimal int of 7.
Finally, using String hexString = Integer.toString(7, 16); would give you a String of "7".
Therefore, when you plug that value into your hexArrayRed[a], instead of plugging it in as #AARRGGBB, you're plugging it in as #AARGGBB which is an improper format.
So to fix this, you simply have to check the length of hexString to see if it only has a size of 1. If it is, append an extra 0 to the front of it when you create your full hex string.

Converting inputFrame from Camera to HSI using OpenCV in Android

I want to convert an image from Android camera to HSI format using OpenCV.
The problem is when I use the following method
private Mat rgb2hsi(Mat rgbFrame) {
Mat hsiFrame = rgbFrame.clone();
for( int i = 0; i < rgbFrame.rows(); ++i ) {
for( int j = 0; j < rgbFrame.cols(); ++j ) {
double[] rgb = rgbFrame.get(i, j);
Log.d(MAINTAG, "rgbFrame.get(i, j) array size = " + rgb.length);
double colorR = rgb[0];
double colorG = rgb[1];
double colorB = rgb[2];
double minRGB = min(colorR, colorG, colorB);
double colorI = (colorR + colorG + colorB) / 3;
double colorS = 0.0;
if(colorI > 0) colorS = 1.0 - (minRGB / colorI);
double colorH;
double const1 = colorR - (colorG / 2) - (colorB / 2);
double const2 = Math.sqrt(Math.pow(colorR, 2) + Math.pow(colorG, 2) + Math.pow(colorR, 2)
- (colorR * colorG) - (colorR * colorB) - (colorG * colorB));
colorH = Math.acos(const1 / const2);
if(colorB > colorG) colorH = 360 - colorH;
double[] hsi = {colorH, colorS, colorI};
hsiFrame.put(i, j, hsi);
}
}
return hsiFrame;
}
It shows an error
java.lang.UnsupportedOperationException: Provided data element number (3) should be multiple of the Mat channels count (4)
I search for a while to figure out the cause of this error.
I found that I put an array of size 3 instead of 4.
Android convert byte array from Camera API to color Mat object openCV
I wonder what Type of image receive from Android Camera.
Why when I get an array of size 4?
How to convert an image received from Android camera to HSI and preview on the screen?
The following is the overrided method onCameraFrame
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
Mat outputFrame = inputFrame.rgba();
/* Get RGB color from the pixel at [index_row, index_column] */
int index_row = 0;
int index_column = 0;
final double[] mRgb_pixel = outputFrame.get(index_row, index_column);
/* Show the result */
runOnUiThread(new Runnable() {
#Override
public void run() {
int r = (int) mRgb_pixel[0];
int g = (int) mRgb_pixel[1];
int b = (int) mRgb_pixel[2];
/* Set RGB color */
mRred_textview.setText("Red\n" + Double.toString(mRgb_pixel[0]));
mGreen_textview.setText("Green\n" + Double.toString(mRgb_pixel[1]));
mBlue_textview.setText("Blue\n" + Double.toString(mRgb_pixel[2]));
mColor_textview.setBackgroundColor(Color.rgb(r, g, b));
}
});
if(mPreviewType == PreviewType.GB) {
outputFrame.convertTo(outputFrame, CvType.CV_64FC3);
return getGBColor(rgb2hsi(outputFrame));
} else if (mPreviewType == PreviewType.HSI) {
outputFrame.convertTo(outputFrame, CvType.CV_64FC3);
return rgb2hsi(outputFrame);
} else {
return outputFrame;
}
}
My MainActivity implements CameraBridgeViewBase.CvCameraViewListener2
[Edit]
I think that the reason why it return an array of size 4 is because the frame is in RGBA format, not RGB format.
Therefore, how to convert RGBA to HSI and preview the frame on the screen?
The problem here is that your hsiFrame is a 4 channel image and your hsi array has only 3 values. You need to add one term corresponding to alpha channel to your hsi array. Making either of the following changes should work for you:
1. double[] hsi = {colorH, colorS, colorI, rgb[3]};
2. Mat hsiFrame = new Mat(rgbFrame.size(), CvType.CV_8UC3);
Hope this helps.

Categories

Resources