如何使用 C++ 搜索具有非白色背景的图像?

Posted

技术标签:

【中文标题】如何使用 C++ 搜索具有非白色背景的图像?【英文标题】:How do you search for images that have a non white background using c++? 【发布时间】:2017-08-07 15:14:26 【问题描述】:

我编写了一个使用 openCV 和 boost::filesystem 库的程序,该程序裁剪图像以适合图像中的对象。 (Photoshop 已经用于将大部分背景替换为白色)。但是,我有成千上万张图片需要整理。我已经知道如何使用文件系统库并且遍历系统目录没有问题。但是,如何检测具有非白色背景的图像(在 Photoshop 过程中丢失)?这个incorrect crop 被格式化为有一个边距并且有一个1:1 的纵横比,但它仍然有奇怪的灰色背景。图像最终应该看起来像这样 correct crop。那么,如何判断图片是否有裁剪不正确的背景呢?

【问题讨论】:

恕我直言,这个问题对于 *** 来说太宽泛了。搜索图像包括: 1)遍历目录 2)打开图像文件 3)使用库来解码文件格式 4)根据需要调整图像 5)比较或搜索位图。项目太多,无法在此处列出。 @ThomasMatthews 我明白你的意思。但是,主要目标是确定图像是否具有完全白色的背景。 如果您发布代码。我可以对其进行必要的修改。 @sturkmen 你只想要代码的裁剪部分吗?因为整件事超过 5000 行。 好的。我将很快发布基于 adrien barral 答案的示例代码。我认为这会有所帮助。确实你有一个裁剪代码。您可以为所有图片重新运行它。如果图片已经裁剪,它将保持不变 【参考方案1】:

你可以试试下面的代码

(要测试代码,您应该创建一个目录 c:/cropping 和一些子目录。并将一些图像放在您创建的目录中。)

希望对你有帮助

#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;

vector<Rect> divideHW(Mat src, int dim, double threshold1, double threshold2)

    Mat gray, reduced, canny;

    if (src.channels() == 1)
    
        gray = src;
    

    if (src.channels() == 3)
    
        Laplacian(src, gray, CV_8UC1);
        cvtColor(gray, gray, COLOR_BGR2GRAY);
        imshow("sobel", gray);
    

    reduce(gray, reduced, dim, REDUCE_AVG);

    Canny(reduced, canny, threshold1, threshold2);

    vector<Point> pts;
    findNonZero(canny, pts);

    vector<Rect> rects;

    Rect rect(0, 0, gray.cols, gray.rows);
    if (!pts.size())
    
        rects.push_back(rect);
    
    int ref_x = 0;
    int ref_y = 0;

    for (size_t i = 0; i< pts.size(); i++)
    
        if (dim)
        
            rect.height = pts[i].y - ref_y;
            rects.push_back(rect);
            rect.y = pts[i].y;
            ref_y = rect.y;
            if (i == pts.size() - 1)
            
                rect.height = gray.rows - pts[i].y;
                rects.push_back(rect);
            
        

        else
        
            rect.width = pts[i].x - ref_x;
            rects.push_back(rect);
            rect.x = pts[i].x;
            ref_x = rect.x;
            if (i == pts.size() - 1)
            
                rect.width = gray.cols - pts[i].x;
                rects.push_back(rect);
            
        

    
    return rects;


int main( int argc, char** argv )

    int wait_time = 0; // set this value > 0 for not waiting 
    vector<String> filenames;
    String folder = "c:/cropping/*.*"; // you can change this value or set it by argv[1]

    glob(folder, filenames, true);

    for (size_t i = 0; i < filenames.size(); ++i)
    

        Mat src = imread(filenames[i]);

        if (src.data)
        
            vector<Rect> rects = divideHW(src, 0, 0, 0);
            if (rects.size() < 3) continue;
            Rect border;
            border.x = rects[0].width;
            border.width = src.cols - rects[rects.size() - 1].width - border.x;

            rects = divideHW(src, 1, 0, 20);
            if (rects.size() < 3) continue;
            border.y = rects[0].height;
            border.height = src.rows - rects[rects.size() - 1].height - border.y;

            Mat cropped = src(border).clone();
            src(border).setTo(Scalar(255, 255, 255));
            Scalar _mean = mean(src);
            int mean_total = _mean[0] + _mean[1] + _mean[2];

            if (mean_total > 763)
            
                imwrite(filenames[i] + ".jpg", cropped);
                imshow("cropped", cropped);
                waitKey(wait_time);
            

        
    
    return 0;

【讨论】:

我想知道您使用此代码的结果。它找到了多少张图片?【参考方案2】:

您可以计算图像 ROI 的梯度(例如,第 10 到 15 列中的所有行)。 然后计算梯度的能量(梯度图像所有像素的总和)。

如果能量非常低,则您有一个均匀的背景(使用此算法您无法知道背景颜色)。否则你有一个带纹理的背景。

这是第一种方法。您可以在 OpenCV 中找到执行此操作所需的所有功能。

第二种方法: 如果你确定你的背景是白色的,你可以得到第一种方法的 ROI,然后遍历所有像素,并检查它的颜色。如果有超过“n”个像素的颜色与“255,255,255”不同,您可以将图像标记为“非白色背景”。

【讨论】:

以上是关于如何使用 C++ 搜索具有非白色背景的图像?的主要内容,如果未能解决你的问题,请参考以下文章

叠加在图像上时,使文本显示为白色,具有半透明的黑色背景

如何在C++中用文字制作图片的白色背景

在LWUIT中,按下按钮时出现白色矩形背景,如何去除?

如何使图像变暗以保持透明度不受 CSS 或 JS 影响?

如何在Android Studio中使图像中的特定颜色透明?

如何使用 PHP 从图像中提取文本