如何提升OpenCV提取的扫描纸张签名质量?含透明背景需求
签名提取与透明背景PNG转换优化需求
我使用OpenCV Java库从扫描的白底签名纸中提取并裁剪签名,目前发现灰度版本(grayROI)的效果最优。希望优化签名外观(如提亮背景),核心需求是将签名转换为带透明背景的PNG格式。现有实现代码如下:
import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.imageio.ImageIO; import org.apache.commons.io.FilenameUtils; import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.core.MatOfPoint; import org.opencv.core.Point; import org.opencv.core.Rect; import org.opencv.core.Scalar; import org.opencv.core.Size; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import org.opencv.utils.Converters; import nu.pattern.OpenCV; public static synchronized void extractSignature(File signature) { if (signature == null) return; String fileExtension = FilenameUtils.getExtension(signature.getName()); // check if the file extension is correct! if (!fileExtension.toLowerCase().equals("jpg") && !fileExtension.toLowerCase().equals("jpeg") && !fileExtension.toLowerCase().equals("png")) { return; } try { if (!isLoaded) { OpenCV.loadLocally(); isLoaded = true; } } catch (Exception e) { System.out.println(e.toString()); } // Load image Mat image = Imgcodecs.imread(signature.getPath()); Mat imageOriginal = image.clone(); // Convert image to HSV color space Mat hsv = new Mat(); Imgproc.cvtColor(image, hsv, Imgproc.COLOR_BGR2HSV); // Define lower and upper bounds for color threshold Scalar lower = new Scalar(90, 38, 0); Scalar upper = new Scalar(145, 255, 255); // Threshold the HSV image to get only desired colors Mat mask = new Mat(); Core.inRange(hsv, lower, upper, mask); // Find contours List<MatOfPoint> contours = new ArrayList<>(); Mat hierarchy = new Mat(); Imgproc.findContours(mask, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); // Combine all contours into one and get bounding box MatOfPoint allContours = new MatOfPoint(); for (MatOfPoint contour : contours) { List<Point> pts = contour.toList(); allContours.push_back(new MatOfPoint(Converters.vector_Point_to_Mat(pts))); } Rect boundingBox = Imgproc.boundingRect(allContours); // Add 5 pixels to each dimension of the bounding box int padding = 10; int x = Math.max(boundingBox.x - padding, 0); int y = Math.max(boundingBox.y - padding, 0); int width = Math.min(boundingBox.width + 2 * padding, image.cols() - x); int height = Math.min(boundingBox.height + 2 * padding, image.rows() - y); Rect paddedBoundingBox = new Rect(x, y, width, height); // Extract ROI //Mat ROI = new Mat(imageOriginal, boundingBox); Mat ROI = new Mat(imageOriginal, paddedBoundingBox); // Convert ROI to grayscale Mat grayROI = new Mat(); Imgproc.cvtColor(ROI, grayROI, Imgproc.COLOR_BGR2GRAY); // Apply histogram equalization to improve contrast Mat equalizedROI = new Mat(); Imgproc.equalizeHist(grayROI, equalizedROI); // Apply adaptive thresholding to binarize the image Mat binaryROI = new Mat(); Imgproc.adaptiveThreshold(grayROI, binaryROI, 255, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY, 11, 2); // Apply morphological transformations to improve the signature appearance Mat morphROI = new Mat(); Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2, 2)); Imgproc.morphologyEx(binaryROI, morphROI, Imgproc.MORPH_CLOSE, kernel); Imgproc.morphologyEx(morphROI, morphROI, Imgproc.MORPH_OPEN, kernel); // Save and display images Imgcodecs.imwrite(FileUtils.getSignaturesFolder().getAbsolutePath() + File.separator + signature.getName(), ROI); Imgcodecs.imwrite(FileUtils.getSignaturesFolder().getAbsolutePath() + File.separator + "morphROI.jpg", morphROI); Imgcodecs.imwrite(FileUtils.getSignaturesFolder().getAbsolutePath() + File.separator + "grayROI.jpg", grayROI); Imgcodecs.imwrite(FileUtils.getSignaturesFolder().getAbsolutePath() + File.separator + "binaryROI.jpg", binaryROI); Imgcodecs.imwrite(FileUtils.getSignaturesFolder().getAbsolutePath() + File.separator + "equalizedROI.jpg", equalizedROI); return; }
参考图片
- 原扫描图:

- 提取结果图:

内容的提问来源于stack exchange,提问作者Paolo
相关产品推荐
相关产品推荐

