如何使用 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++ 搜索具有非白色背景的图像?的主要内容,如果未能解决你的问题,请参考以下文章