[問題] 關於影像處理

看板AndroidDev作者時間10年前 (2014/03/11 20:13), 編輯推噓2(2020)
留言22則, 5人參與, 最新討論串1/1
各位大大好 小弟目前利用 mamaya3 大大的 照相機預覽的程式 在 Nexus 7 上抓到了底層回傳的 Camera preview raw data(NV21格式) 並解碼成RGB格式 我的問題是 想保留畫面上的紅色部分 其餘部分轉成灰階 類似像這張圖 http://ppt.cc/j53Q 可是 "影像處理完後,全變成藍色濾鏡的效果" 像這樣 http://ppt.cc/9NfV >"< ******************************************************************* 我的做法是除了滿足 1. pixel RGB 的 R 分量是否等於 255 2. pixel RGB 的 G 分量等於 0 3. pixel RGB 的 B 分量等於 0 的像素點不做修改 其餘的像素點通通改成灰階 也就是紅色的點保留不除理,剩餘的通通改成灰階 ******************************************************************* 以下是我在客製化View中 (就是不斷更新預覽畫面的View) 覆寫的 onDraw 方法的程式碼,總 若是有需要其餘的java檔,小弟可在上傳 感謝板上高手 ^.^ =================================================================== @Override protected void onDraw(Canvas canvas){ Log.i(tag, "onDraw() "); //image 可以是framework 傳到 Application 層的 preview raw data int size = imgWidth * imgHeight; int[] rgb = new int[imgWidth * imgHeight]; if(isCameraSet){ rgb = convertYUV420_NV21toARGB8888(image, imgWidth, imgHeight); for (int k = 0; k < size; k++) { if(Color.red(rgb[k]) == 255 && Color.green(rgb[k]) == 0 && Color.blue(rgb[k]) == 0){} else{ rgb[k] = (int) ((0.2126 * Color.red(rgb[k])) + (0.7152 * Color.green(rgb[k])) + (0.0722 * Color.blue(rgb[k]))); } } Log.i("tag", "rgb length = " + rgb.length); overlayBitmap = Bitmap.createBitmap(rgb, 0, imgWidth, imgWidth,imgHeight, Bitmap.Config.RGB_565); canvas.drawBitmap(overlayBitmap, matrix, null); overlayBitmap.recycle(); } } ======================================================================== 完整的 ViewToDraw 程式碼 package com.example.macampreviewdemo; public class ViewToDraw extends View{ public String tag = "tag"; public byte[] image; public boolean isCameraSet = false; public int imgWidth, imgHeight; Bitmap overlayBitmap; Matrix matrix; public ViewToDraw(Context context, AttributeSet attrs) { super(context, attrs); matrix = new Matrix(); } public void cameraSet(){ isCameraSet = true; } public void putImage(byte[] img){ image = img; } @Override protected void onDraw(Canvas canvas){ Log.i(tag, "onDraw() "); //image 可以是framework 傳到 Application 層的 preview raw data int size = imgWidth * imgHeight; int[] rgb = new int[imgWidth * imgHeight]; if(isCameraSet){ rgb = convertYUV420_NV21toARGB8888(image, imgWidth, imgHeight); for (int k = 0; k < size; k++) { if(Color.red(rgb[k]) == 255 && Color.green(rgb[k]) == 0 && Color.blue(rgb[k]) == 0){} else{ rgb[k] = (int) ((0.2126 * Color.red(rgb[k])) + (0.7152 * Color.green(rgb[k])) + (0.0722 * Color.blue(rgb[k]))); } } Log.i("tag", "rgb length = " + rgb.length); overlayBitmap = Bitmap.createBitmap(rgb, 0, imgWidth, imgWidth, imgHeight, Bitmap.Config.RGB_565); canvas.drawBitmap(overlayBitmap, matrix, null); overlayBitmap.recycle(); } } /** * Converts YUV420 NV21 to ARGB8888 * * @param data byte array on YUV420 NV21 format. * @param width pixels width * @param height pixels height * @return a ARGB8888 pixels int array. Where each int is a pixels ARGB. */ public static int[] convertYUV420_NV21toARGB8888(byte[] data, int width, int height) { int size = width*height; int offset = size; int[] pixels = new int[size]; int u, v, y1, y2, y3, y4; // i along Y and the final pixels // k along pixels U and V for(int i=0, k=0; i < size; i+=2, k+=1) { y1 = data[i ]&0xff; y2 = data[i+1]&0xff; y3 = data[width+i ]&0xff; y4 = data[width+i+1]&0xff; v = data[offset+k ]&0xff; u = data[offset+k+1]&0xff; v = v-128; u = u-128; pixels[i ] = convertYUVtoARGB(y1, u, v); pixels[i+1] = convertYUVtoARGB(y2, u, v); pixels[width+i ] = convertYUVtoARGB(y3, u, v); pixels[width+i+1] = convertYUVtoARGB(y4, u, v); if (i!=0 && (i+2)%width==0) i+=width; } return pixels; } private static int convertYUVtoARGB(int y, int u, int v) { int r,g,b; r = y + (int)(1.402f*u); g = y - (int)(0.344f*v + 0.714f*u); b = y + (int)(1.772f*v); r = r>255? 255 : r<0 ? 0 : r; g = g>255? 255 : g<0 ? 0 : g; b = b>255? 255 : b<0 ? 0 : b; return 0xff000000 | (r<<16) | (g<<8) | b; } } -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 59.124.161.210

03/11 21:06, , 1F
我沒看你的code 不過紅色的threshold用255不會太大嗎
03/11 21:06, 1F

03/11 21:25, , 2F
"保留紅色部分" 的條件會再做調整,感謝大大意見 ^^
03/11 21:25, 2F

03/11 22:57, , 3F
不太懂影像處理,但有個小疑問~您轉成灰階的公式…轉出來
03/11 22:57, 3F

03/11 23:00, , 4F
不是Y(0~255)嗎?但您是用RGB的格式去產生新圖@@",這樣
03/11 23:00, 4F

03/11 23:00, , 5F
是ok的嗎O_Q?
03/11 23:00, 5F

03/11 23:13, , 6F
轉灰階的那一行改成:rgb[k] = rgb[k]<<16 | rgb[k]<<8 |
03/11 23:13, 6F

03/11 23:13, , 7F
rgb[k]試試~~O_Q"
03/11 23:13, 7F

03/11 23:19, , 8F
你紅色取值太極端了 做完可能都當成雜訊了...
03/11 23:19, 8F

03/11 23:30, , 9F
對了,而且如果用你轉灰階的方法就會變成...
03/11 23:30, 9F

03/11 23:31, , 10F
value = 0x0000xx(R=00, G=00, B=xx, xx=[0, 255])這樣可
03/11 23:31, 10F

03/11 23:32, , 11F
能就可以解釋為什麼會被遮上一層藍色的東西了~~((小弟一
03/11 23:32, 11F

03/11 23:33, , 12F
點拙見~如有不對地方請指正…((小聲說~我也覺得threshold
03/11 23:33, 12F

03/11 23:34, , 13F
可以再取的適切一些@@"~~~~~
03/11 23:34, 13F

03/12 01:32, , 14F
感謝S大跟G大的意見,我再把保留紅色的條件放寬~
03/12 01:32, 14F

03/12 01:34, , 15F
我先看一下G大的解釋, 感謝各位高手 !!!
03/12 01:34, 15F

03/12 01:37, , 16F
請教G大, value = 0x0000xx(R=00..xx=[0,255]) 這行的
03/12 01:37, 16F

03/12 01:38, , 17F
原因我不太明白
03/12 01:38, 17F

03/12 09:20, , 18F
請問原PO大,您試過我所說的轉換方式後,有正常嗎@@????
03/12 09:20, 18F

03/12 09:21, , 19F
如果不正常~~~我講的解釋可能都會變成嘴砲XDDDDDDDD"
03/12 09:21, 19F

03/12 09:22, , 20F
畢竟上面那些轉換方式,只是小弟的猜測O_Q"~~~~~
03/12 09:22, 20F

03/12 10:34, , 22F
參考看看?
03/12 10:34, 22F
文章代碼(AID): #1J7ltW0A (AndroidDev)