Imagen de umbral Blanco-Blanco en tiempo real de Android
Tengo un código que convierte un mapa de bits que tiene los colores grises en un mapa de bits de colores en blanco y negro, utilizando este código:
// scan through all pixels for (int x = 0; x < width; ++x) { for (int y = 0; y < height; ++y) { // get pixel color pixel = bitmap.getPixel(x, y); A = Color.alpha(pixel); R = Color.red(pixel); G = Color.green(pixel); B = Color.blue(pixel); int gray = (int) (0.2989 * R + 0.5870 * G + 0.1140 * B); // use 128 as threshold, above -> white, below -> black if (gray > 128) gray = 255; else gray = 0; // set new pixel color to output bitmap bmOut.setPixel(x, y, Color.argb(A, gray, gray, gray)); } }
Como puedes ver, viajo todos los puntos de píxeles del mapa de bits original y luego comparo los componentes del color con un umbral dado, en este caso 128, y luego si su anterior digo su blanco de lo contrario será un píxel negro.
- Imagen seleccionada de gallary no va a establecer en ImageView
- Bitmap demasiado grande para ser cargado en una textura
- Guardar un edittext en un mapa de bits
- Android procesamiento de imágenes de alta resolución
- Desconcertado por el valor de píxeles en Bitmap (pre multiplicado usando setPixel)
Lo que quiero hacer ahora, es un Spinner que puede cambiar ese valor umbral, y luego la imagen BW será diferente.
Para hacer esto, tendría que dibujar toda la imagen de nuevo, y eso es muy cpu que cuesta el tiempo, su toma el tiempo para viajar todos los pixeles otra vez.
¿Hay alguna manera de cambiar la imagen usando un umbral de BW diferente en tiempo real?
Alguien me dijo que usar un GIF, y luego lo que yo haría, sólo estaba cambiando los valores de la tabla de búsqueda del GIF, ¿alguien tiene conocimiento sobre esto en Android?
- ¿Cómo adjuntar la imagen de drawable a gmail?
- La aplicación se bloquea al escalar el mapa de bits en lienzo
- Android rotar mapa de bits sin hacer una copia
- Dibujar líneas transparentes en el mapa de bits a través de la entrada táctil
- Android: ¿cómo administrar el tamaño de mapa de bits al dibujar a pantallas de diferentes tamaños?
- Cómo hacer que el movimiento de caída de nieve para un mapa de bits en Android
- Consenso sobre la carga lenta de mapas de bits en un adaptador (énfasis en Bitmap.recycle ())
- DrawBitmap: ¿Cómo se pueden establecer coordenadas y utilizar una matriz?
Te recomiendo que mires usando la biblioteca OpenCV para Android. Una vez que lo tiene instalado puede utilizarlo para el umbral rápido entre muchas otras operaciones de uso común en las imágenes. El fragmento de código siguiente convertirá su bitamp de color en una imagen gris y umbral en el nivel de gris 128.
// first convert bitmap into OpenCV mat object Mat imageMat = new Mat (bitmap.getHeight(), bitmap.getWidth(), CvType.CV_8U, new Scalar(4)); Bitmap myBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true); Utils.bitmapToMat(myBitmap, imageMat); // now convert to gray Mat grayMat = new Mat ( bitmap.getHeight(), bitmap.getWidth(), CvType.CV_8U, new Scalar(1)); Imgproc.cvtColor(imageMat, grayMat, Imgproc.COLOR_RGB2GRAY, 1); // get the thresholded image Mat thresholdMat = new Mat ( bitmap.getHeight(), bitmap.getWidth(), CvType.CV_8U, new Scalar(1)); Imgproc.threshold(grayMat, thresholdMat , 128, 255, Imgproc.THRESH_BINARY); // convert back to bitmap for displaying Bitmap resultBitmap = Bitmap.createBitmap(bitmap.cols(), bitmap.rows(), Bitmap.Config.ARGB_8888); thresholdMat.convertTo(thresholdMat, CvType.CV_8UC1); Utils.matToBitmap(thresholdMat, resultBitmap);
Pasó un poco de tiempo desde que se hizo esta pregunta, pero me topé con esto buscando algo más y pasó a tener la solución. Puede lograr esto sin OpenCV o cualquier otra biblioteca de terceros, utilizando sólo ColorMatrixColorFilter disponible desde el nivel 1 de la API.
Aquí están las matrices que usted puede utilizar:
//matrix that changes picture into gray scale public static ColorMatrix createGreyMatrix() { ColorMatrix matrix = new ColorMatrix(new float[] { 0.2989f, 0.5870f, 0.1140f, 0, 0, 0.2989f, 0.5870f, 0.1140f, 0, 0, 0.2989f, 0.5870f, 0.1140f, 0, 0, 0, 0, 0, 1, 0 }); return matrix; } // matrix that changes gray scale picture into black and white at given threshold. // It works this way: // The matrix after multiplying returns negative values for colors darker than threshold // and values bigger than 255 for the ones higher. // Because the final result is always trimed to bounds (0..255) it will result in bitmap made of black and white pixels only public static ColorMatrix createThresholdMatrix(int threshold) { ColorMatrix matrix = new ColorMatrix(new float[] { 85.f, 85.f, 85.f, 0.f, -255.f * threshold, 85.f, 85.f, 85.f, 0.f, -255.f * threshold, 85.f, 85.f, 85.f, 0.f, -255.f * threshold, 0f, 0f, 0f, 1f, 0f }); return matrix; }
Y aquí es cómo usarlos:
BitmapFactory.Options options = new BitmapFactory.Options(); options.inScaled = false; //load source bitmap and prepare destination bitmap Bitmap pic = BitmapFactory.decodeResource(getResources(), R.drawable.thePicture, options); Bitmap result = Bitmap.createBitmap(pic.getWidth(), pic.getHeight(), Bitmap.Config.ARGB_8888); Canvas c = new Canvas(result); //first convert bitmap to grey scale: bitmapPaint.setColorFilter(new ColorMatrixColorFilter(createGreyMatrix())); c.drawBitmap(pic, 0, 0, bitmapPaint); //then convert the resulting bitmap to black and white using threshold matrix bitmapPaint.setColorFilter(new ColorMatrixColorFilter(createThresholdMatrix(128))); c.drawBitmap(result, 0, 0, bitmapPaint); //voilà! You can now draw the result bitmap anywhere You want: bitmapPaint.setColorFilter(null); otherCanvas.drawBitmap(result, null, new Rect(x, y, x + size, y + size), bitmapPaint);
Espero que esto ayude a alguien.
GIFs tienen una paleta de colores en la cabecera que asocia, para cada "valor", que color pertenece a ella ( entrada de Wikipedia ). La captura: en el día que pensaban que 256 colores sería suficiente, y que es tantas entradas de paleta que hay. Podrías usar la clase GifDecoder.java con una tabla de color local de 256 entradas y dos valores: tus dos salidas 0 y 255. Pero al final del día, hay un bucle que comprueba cada byte , qué valor asociar a través de la paleta ( Esta es la línea ). No es un poco más rápido que su código.
Una alternativa para hacer esto más rápido podría ser el uso de OpenGL para producir su umbral (dado que de todos modos usted va a dibujar el mapa de bits en la pantalla, ¿verdad?). Esto necesita un montón de código extra, afortunadamente este tutorial hace exactamente lo que quieres hacer, menos la parte de umbral.
Para el umbral, un programa OpenGL necesita ser compilado (en GlRenderer::onSurfaceChanged
) y utilizado cada vez (en GlRenderer::onDrawFrame
). El programa obtiene dos sombreadores que el umbral de cada píxel a la velocidad de la luz! (OK, tal vez un poco más lento, pero muy rápido!).
Los shaders serían como los siguientes. Déjeme saber si puedo ayudarle con conectarlos en el código de ejemplo.
private static final String mVertexShader = "attribute vec4 aPosition;\n" + "attribute vec4 aTextureCoord;\n" + "varying vec2 vTextureCoord;\n" + "void main() {\n" + " gl_Position = aPosition;\n" + " vTextureCoord = aTextureCoord;\n" + "}\n"; private static final String mFragmentShader = "precision mediump float;\n" + "varying vec2 vTextureCoord;\n" + "uniform float threshold_in_range_0_to_1;\n" + "const vec4 coeff_y = vec4(0.256, 0.504, 0.097, 0.0625);\n" + "float y;\n" + "void main() {\n" + " y = dot(coeff_y, texture2D(sTexture, vTextureCoord));\n" + " if ( y > threshold_in_range_0_to_1)" + " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0)\n" + " else" + " gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0)\n" + "}\n";
- Cómo centrar el menú de acciones en la barra de herramientas
- Cómo emular un navegador móvil (android) en el escritorio