我想找到显示器中存在的每个坏像素。坏像素可能是颜色不正确的像素,或者像素只是黑色。显示屏的尺寸为 160x320 像素。所以如果显示效果好的话,必须有160*320=51200像素。如果显示器没有 51200 像素,那就是坏的。另外,我想知道每个坏像素的位置。
一旦拍摄的图像太大,我将共享一个谷歌驱动器共享文件夹,其中包含良好显示器和包含不良像素的不良显示器的示例。
你能帮我怎么做吗?我想用 opencv 在 python 中做到这一点。
提前致谢
我尝试通过检测到的对象的轮廓进行评估,并且它有效,但前提是所有像素都存在。如果一个像素丢失并且没有检测到轮廓,我可以知道一个像素丢失,但我无法知道它的位置。
所以我认为最好的解决方案是跟踪网格并评估网格的每个单元。
这是我当前的代码:
import cv2
import numpy as np
import matplotlib.pyplot as plt
def getColor(area):
if area > 70:
return (255, 0, 0)
if area < 14:
return (0, 0, 255)
return (255, 255, 0)
def test_green_pattern():
mask = cv2.imread("masks/mask.bmp", 0)
green = cv2.imread("images/green-good.bmp")
green_W = cv2.addWeighted(green, 3, green, 0, 1)
gray = cv2.cvtColor(green_W, cv2.COLOR_BGR2GRAY)
masked = cv2.bitwise_and(gray, gray, mask=mask)
cv2.imwrite("try/green-masked.bmp", masked)
# Real threshold = 120
ret, thresh = cv2.threshold(masked, 120, 255, cv2.THRESH_BINARY)
cv2.imwrite("try/green-threshold.bmp", thresh)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
print("Green Pattern Pixels:", len(contours))
areas = []
perimeters = []
bad = 0
prob_double = 0
qtd = 0
for i, contour in enumerate(contours):
area = area = cv2.contourArea(contour)
areas.append(area)
perimeter = cv2.arcLength(contour,True)
perimeters.append(perimeter)
color = getColor(area)
if area < 14:
bad += 1
qtd += 1
x, y, width, height = cv2.boundingRect(contour)
roi = green[y:y+height, x:x+width]
cv2.imwrite("try/temp/"+str(i)+".bmp", roi)
cv2.drawContours(green, contour, -1, color, 1)
cv2.drawContours(green_W, contour, -1, color, 1)
if area > 90:
prob_double += 1
qtd += 2
cv2.drawContours(green, contour, -1, color, 1)
cv2.drawContours(green_W, contour, -1, color, 1)
else:
qtd += 1
#get_statistics(areas, perimeters)
print("Total:",qtd)
print("Probably double pixel:", prob_double)
print("Bad pixels:", bad)
cv2.imwrite("try/green-contours.bmp", green)
cv2.imwrite("try/green_w-contours.bmp", green_W)
test_green_pattern()
@吉列尔梅·门德斯
编辑:计算时间更少。 green-bad.bmp:35秒--->5秒
1.求轮廓质心
2.找到同一列的质心点
3.插入点于
坏像素
连接
好/坏像素
有蓝/红线
输入:green-bad.bmp
输出: c,r= 211 , 30 c,r= 211 , 30
输入:green-good.bmp
输出:无
#include <QtWidgets/QApplication>
#include <QPainter>
#include <QTimer>
#include <QDebug>
#include <vector>
#include <map>
#include<list>
#include <iterator>
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
using namespace cv;
using namespace std;
class MyPoint3
{
public:
MyPoint3(int _x=0,int _y=0,int _z=0):x(_x),y(_y),z(_z)
{}
int x, y, z;
Point cvPoint()
{
return Point(x, y);
}
bool operator==(const MyPoint3& rhs)
{
return x == rhs.x && y == rhs.y && z == rhs.z;
}
MyPoint3(const MyPoint3& rhs)
{
x = rhs.x;
y = rhs.y;
z = rhs.z;
}
MyPoint3&operator=(const MyPoint3& rhs)
{
x = rhs.x;
y = rhs.y;
z = rhs.z;
return *this;
}
};
void findnearpts(vector<MyPoint3>&col,vector<MyPoint3>&pts, MyPoint3 ptrun)
{
vector<MyPoint3> nearpts;
pts.erase(find(pts.begin(), pts.end(), ptrun));
col.push_back(ptrun);
size_t j = 0;
for (;j < pts.size() ; j++)
{
auto iter0 = pts.at(j);
if (iter0.x - ptrun.x > -8)
{
break;
}
}
for (; j < pts.size() ; j++)
{
auto iter0 = pts.at(j);
if (iter0.x - ptrun.x > 8)
{
break;
}
if (fabs(ptrun.y - iter0.y) < 20)
{
nearpts.push_back(iter0);
}
}
for (auto& a : nearpts)
{
findnearpts(col,pts, a);
}
}
int main2(int argc, char* argv[]);
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QString str = "c:/Users/qt/Downloads/Displays-20230404T035654Z-001/Displays/";
auto src = imread((str + "green-bad.bmp").toUtf8().constData());
//addWeighted(src, 3, src, 0, 1,src);
imwrite((str + "green-bad-strong.bmp").toUtf8().constData(), src);
Mat dst, dst2,dst3;
// You can try more different parameters
cvtColor(src, dst, COLOR_RGBA2GRAY, 0);
imwrite((str + "green-bad-gray.bmp").toUtf8().constData(), dst);
threshold(dst, dst2, 41, 255, THRESH_BINARY);
imwrite((str + "green-bad-binary.bmp").toUtf8().constData(), dst2);
//morphologyEx(dst2, dst3, MORPH_CLOSE, getStructuringElement(MORPH_RECT, Size(6,6)));
//imwrite((str + "green-bad-binary-closing.bmp").toUtf8().constData(), dst3);
//main2(argc, argv);
vector<vector<Point> > contours0;
vector<Vec4i> hierarchy;
findContours(dst2, contours0, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE);
Mat matpt(src.size(), CV_8UC3,Scalar(0,0,0));
typedef cv::Point3_<uint8_t> Pixel;
vector<MyPoint3> points;
for (auto& a : contours0)
{
auto M = moments(a);
auto cx = int(M.m10 / M.m00);
auto cy = int(M.m01 / M.m00);
points.push_back(MyPoint3(cx, cy,0));
line(matpt, Point(cx, cy), Point(cx, cy), Scalar(255, 255, 255));
}
imwrite((str + "green-bad-center.bmp").toUtf8().constData(), matpt);
std::sort(points.begin(), points.end(), [&](MyPoint3 a, MyPoint3 b) {return a.x < b.x; });
const int height = 160,width=320;
vector<vector<MyPoint3>> cols;
cols.reserve(width);
for (;!points.empty();)
{
vector<MyPoint3> tmpcol;
findnearpts(tmpcol, points, points[0]);
cols.push_back(tmpcol);
}
qDebug() << "test1" << endl;
for (auto& colrun : cols)
{
std::sort(colrun.begin(), colrun.end(), [&](MyPoint3 a, MyPoint3 b) {return a.y < b.y; });
}
qDebug() << "test2" << endl;
for (int nfind = 1; nfind;)
{
for (size_t i = 0; i < cols.size(); i++)
{
if (cols.at(i).size() != height)
{
nfind = 1;
for (size_t j = 0; j < cols.size(); j++)
{
if (i != j
&& cols.at(j).size() != height
&&
(fabs(cols.at(i).begin()->x - cols.at(j).rbegin()->x) < 8
|| fabs(cols.at(i).rbegin()->x - cols.at(j).begin()->x) < 8
)
)
{
vector<MyPoint3> tmppts;
if (cols.at(i).begin()->y < cols.at(j).begin()->y)
{
tmppts.insert(tmppts.end(), cols.at(i).begin(), cols.at(i).end());
tmppts.insert(tmppts.end(), MyPoint3(cols.at(j).begin()->x, .5 * (cols.at(j).begin()->y + cols.at(i).rbegin()->y), 1));
tmppts.insert(tmppts.end(), cols.at(j).begin(), cols.at(j).end());
}
else
{
tmppts.insert(tmppts.end(), cols.at(j).begin(), cols.at(j).end());
tmppts.insert(tmppts.end(), MyPoint3(cols.at(i).begin()->x, .5 * (cols.at(j).rbegin()->y + cols.at(i).begin()->y), 1));
tmppts.insert(tmppts.end(), cols.at(i).begin(), cols.at(i).end());
}
if (i > j)
{
cols.erase(cols.begin() + i);
cols.erase(cols.begin() + j);
}
else
{
cols.erase(cols.begin() + j);
cols.erase(cols.begin() + i);
}
cols.push_back(tmppts);
}
}
}
else
{
nfind = 0;
}
}
}
qDebug() << "test3" << endl;
std::sort(cols.begin(), cols.end(), [&](vector<MyPoint3>& a, vector<MyPoint3>& b) {return a.at(0).x < b.at(0).x; });
qDebug() << "test4" << endl;
int colnumber = 0;
for (auto& colrun : cols)
{
for (size_t i = 0; i+1 < colrun.size(); i++)
{
MyPoint3 p1 = colrun.at(i), p2 = colrun.at(i + 1);
Scalar sc(255, 0, 0);
if (p1.z || p2.z)
{
sc = Scalar(0, 0, 255);
qDebug() << "c,r=" << colnumber << "," << (p1.z?i:i+1) << endl;
}
line(src,p1.cvPoint() ,p2.cvPoint(), sc);
}
colnumber++;
}
imwrite((str + "green-bad-cols.bmp").toUtf8().constData(), src);
return a.exec();
}