You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS+OpenCV扫描文档画质不佳,求优化方案(附处理代码)

Improving Document Scan Quality with OpenCV on iOS (Matching Scannable App Results)

I get it—trying to replicate that crisp, professional scan quality from apps like Scannable with OpenCV can feel frustrating. Your current code snippet shows you’re starting with a basic brightness adjustment (cv::multiply), but Scannable relies on a layered pipeline of advanced image processing steps that go way beyond global tweaks. Let’s break down the key techniques you’re missing and how to implement them with OpenCV on iOS:

Key Steps to Match Scannable’s Quality

1. Adaptive Thresholding (Instead of Fixed Brightness/Contrast)

Scannable doesn’t just crank up brightness globally—it adjusts to local lighting variations (like shadows or uneven illumination). Replace your fixed multiply operation with adaptive thresholding:

// Convert to grayscale first (critical for thresholding)
cv::Mat grayMat;
cv::cvtColor(originalMat, grayMat, cv::COLOR_RGBA2GRAY);

// Apply adaptive Gaussian thresholding to handle uneven lighting
cv::Mat threshMat;
cv::adaptiveThreshold(
    grayMat, threshMat, 255,
    cv::ADAPTIVE_THRESH_GAUSSIAN_C, cv::THRESH_BINARY,
    11, // Block size (adjust based on document size)
    2   // Constant subtracted from mean
);

2. Automatic Perspective Correction

Scannable automatically detects document edges and straightens skewed scans. You’ll need to add contour detection and perspective warping:

// Find contours in the thresholded image
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(threshMat.clone(), contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

// Sort contours by area to pick the largest one (your document)
std::sort(contours.begin(), contours.end(), [](const std::vector<cv::Point>& a, const std::vector<cv::Point>& b) {
    return cv::contourArea(a) > cv::contourArea(b);
});

// Approximate the contour to a quadrilateral (document edges)
std::vector<cv::Point> approx;
cv::approxPolyDP(contours[0], approx, cv::arcLength(contours[0], true) * 0.02, true);

// Apply perspective warp to straighten the document
cv::Mat warpMat = cv::getPerspectiveTransform(
    cv::Mat(approx), 
    cv::Mat(std::vector<cv::Point>{
        cv::Point(0,0), 
        cv::Point(originalMat.cols,0), 
        cv::Point(originalMat.cols, originalMat.rows), 
        cv::Point(0, originalMat.rows)
    })
);
cv::Mat warpedMat;
cv::warpPerspective(originalMat, warpedMat, warpMat, originalMat.size());

3. White Balance Correction

Scannable removes yellowish tints and makes whites look pure. Use the gray world assumption for a simple but effective fix:

cv::Mat floatMat;
originalMat.convertTo(floatMat, CV_32F);

// Calculate average color channels
cv::Scalar avg = cv::mean(floatMat);
float avgGray = (avg[0] + avg[1] + avg[2]) / 3.0;

// Adjust each channel to balance white
floatMat.forEach<cv::Vec4f>([avgGray, avg](cv::Vec4f& pixel, const int* position) -> void {
    pixel[0] *= (avgGray / avg[0]);
    pixel[1] *= (avgGray / avg[1]);
    pixel[2] *= (avgGray / avg[2]);
});

// Convert back to 8-bit and normalize
cv::normalize(floatMat, floatMat, 0, 255, cv::NORM_MINMAX);
floatMat.convertTo(originalMat, CV_8UC4);

4. Noise Reduction (Without Blurring Edges)

Scannable keeps text edges sharp while reducing grain. Use bilateral filtering instead of Gaussian blur:

cv::Mat denoisedMat;
cv::bilateralFilter(grayMat, denoisedMat, 9, 75, 75);

5. Local Contrast Enhancement with CLAHE

Instead of global contrast adjustments, use Contrast Limited Adaptive Histogram Equalization (CLAHE) to boost detail in dark areas without overexposing bright ones:

cv::Ptr<cv::CLAHE> clahe = cv::createCLAHE(2.0, cv::Size(8,8));
clahe->apply(grayMat, grayMat);

Putting It All Together

Run these steps in this order for best results:

  1. White balance correction
  2. Denoising with bilateral filter
  3. Edge detection & perspective correction
  4. Adaptive thresholding or CLAHE enhancement

By combining these techniques, you’ll get much closer to the polished, professional scans Scannable produces.

内容的提问来源于stack exchange,提问作者Mital Solanki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:21:32