我正在尝试构建一个可以从图像中删除单色边框的程序。
边框始终为白色,但左右边框的宽度可能与上下边框的宽度不同。所以我要提取的图像位于源图像的中心。
所以我想从下图中提取绿色矩形。
目前我不知道如何开始解决这个问题。
更新
所以最终 calsign 的代码 fragment 和一些改进解决了我的问题。我意识到内部图像周围的边框可能不是完全单一的颜色,而是会略有不同。这会导致某些图像留下小边框的行为。
我通过用一个阈值比较两种颜色的颜色距离来改进两个像素颜色的比较,从而解决了这个问题。当距离低于阈值时,颜色将被同等处理。
public Bitmap cropBorderFromBitmap(Bitmap bmp) {
//Convenience variables
int width = bmp.getWidth();
int height = bmp.getHeight();
int[] pixels = new int[height * width];
//Load the pixel data into the pixels array
bmp.getPixels(pixels, 0, width, 0, 0, width, height);
int length = pixels.length;
int borderColor = pixels[0];
//Locate the start of the border
int borderStart = 0;
for(int i = 0; i < length; i ++) {
// 1. Compare the color of two pixels whether they differ
// 2. Check whether the difference is significant
if(pixels[i] != borderColor && !sameColor(borderColor, pixels[i])) {
Log.i(TAG,"Current Color: " + pixels[i]);
borderStart = i;
break;
}
}
//Locate the end of the border
int borderEnd = 0;
for(int i = length - 1; i >= 0; i --) {
if(pixels[i] != borderColor && !sameColor(borderColor, pixels[i])) {
Log.i(TAG,"Current Color: " + pixels[i]);
borderEnd = length - i;
break;
}
}
//Calculate the margins
int leftMargin = borderStart % width;
int rightMargin = borderEnd % width;
int topMargin = borderStart / width;
int bottomMargin = borderEnd / width;
//Create the new, cropped version of the Bitmap
bmp = Bitmap.createBitmap(bmp, leftMargin, topMargin, width - leftMargin - rightMargin, height - topMargin - bottomMargin);
return bmp;
}
private boolean sameColor(int color1, int color2){
// Split colors into RGB values
long r1 = (color1)&0xFF;
long g1 = (color1 >>8)&0xFF;
long b1 = (color1 >>16)&0xFF;
long r2 = (color2)&0xFF;
long g2 = (color2 >>8)&0xFF;
long b2 = (color2 >>16)&0xFF;
long dist = (r2 - r1) * (r2 - r1) + (g2 - g1) * (g2 - g1) + (b2 - b1) *(b2 - b1);
// Check vs. threshold
return dist < 200;
}
最佳答案
也许不是使用 API 寻找解决方案的最佳方法,而是想到的方法:直接修改图像的像素。
您可以使用getPixels()
获取位图
的像素|然后用 createBitmap()
创建一个新的、裁剪过的 Bitmap
.然后,这只是找到边界尺寸的问题。
您可以通过访问位于位置 0
的像素找到边框的颜色,然后将该值(int
)与每个后续像素的值进行比较直到你到达边界(不是那种颜色的像素)。只需一点数学知识,就可以做到。
下面是一些演示这一点的简单代码:
private void cropBorderFromBitmap(Bitmap bmp) {
int[] pixels;
//Load the pixel data into the pixels array
bmp.getPixels(pixels, 0, width, 0, 0, width, height);
//Convenience variables
int width = bmp.getWidth();
int height = bmp.getHeight();
int length = pixels.length;
int borderColor = pixels[0];
//Locate the start of the border
int borderStart;
for(int i = 0; i < length; i ++) {
if(pixels[i] != borderColor) {
borderStart = i;
break;
}
}
//Locate the end of the border
int borderEnd;
for(int i = length - 1; i >= 0; i --) {
if(pixels[i] != borderColor) {
borderEnd = length - i;
break;
}
}
//Calculate the margins
int leftMargin = borderStart % width;
int rightMargin = borderEnd % width;
int topMargin = borderStart / width;
int bottomMargin = borderEnd / width;
//Create the new, cropped version of the Bitmap
bmp = createBitmap(bmp, leftMargin, topMargin, width - leftMargin - rightMargin, height - topMargin - bottomMargin);
}
这是未经测试的并且缺乏错误检查(例如,如果宽度为 0 怎么办?),但它应该作为概念验证。
编辑:我刚刚意识到我未能完成 getPixels()
方法。测试您的代码的奇迹……它现在已修复。
关于java - 如何从图像中删除宽度未知的边框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12253739/